@liiift-studio/deploy-vercel-from-sanity 1.0.1 → 1.0.3

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
@@ -19,8 +19,10 @@ interface VercelDeployment {
19
19
  /** Preview hostname, e.g. my-project-abc123.vercel.app */
20
20
  url: string;
21
21
  state: VercelDeployState;
22
- /** Unix ms timestamp */
22
+ /** Unix ms timestamp — when the deployment was created */
23
23
  created: number;
24
+ /** Unix ms timestamp — when the deployment became ready */
25
+ ready?: number;
24
26
  /** Link to the Vercel dashboard page for this deployment */
25
27
  inspectorUrl?: string;
26
28
  creator?: {
package/dist/index.d.ts CHANGED
@@ -19,8 +19,10 @@ interface VercelDeployment {
19
19
  /** Preview hostname, e.g. my-project-abc123.vercel.app */
20
20
  url: string;
21
21
  state: VercelDeployState;
22
- /** Unix ms timestamp */
22
+ /** Unix ms timestamp — when the deployment was created */
23
23
  created: number;
24
+ /** Unix ms timestamp — when the deployment became ready */
25
+ ready?: number;
24
26
  /** Link to the Vercel dashboard page for this deployment */
25
27
  inspectorUrl?: string;
26
28
  creator?: {
package/dist/index.js CHANGED
@@ -35,7 +35,6 @@ var import_icons5 = require("@sanity/icons");
35
35
 
36
36
  // src/components/DeployItem.tsx
37
37
  var import_react2 = require("react");
38
- var import_react_dom = require("react-dom");
39
38
  var import_ui3 = require("@sanity/ui");
40
39
  var import_icons2 = require("@sanity/icons");
41
40
 
@@ -357,16 +356,18 @@ function DeployItem({ target, token, onDelete, onEdit }) {
357
356
  if (timerRef.current) clearInterval(timerRef.current);
358
357
  };
359
358
  }, [isActive, latest?.created]);
360
- const deploy = (0, import_react2.useCallback)(async () => {
359
+ const deploy = (0, import_react2.useCallback)(() => {
361
360
  setDeployError(null);
362
- (0, import_react_dom.flushSync)(() => setTriggering(true));
363
- try {
364
- await triggerDeploy(target.url);
365
- setTimeout(fetchDeployments, 2e3);
366
- } catch (err) {
367
- setTriggering(false);
368
- setDeployError(err instanceof Error ? err.message : "Deploy failed");
369
- }
361
+ setTriggering(true);
362
+ void (async () => {
363
+ try {
364
+ await triggerDeploy(target.url);
365
+ setTimeout(fetchDeployments, 2e3);
366
+ } catch (err) {
367
+ setTriggering(false);
368
+ setDeployError(err instanceof Error ? err.message : "Deploy failed");
369
+ }
370
+ })();
370
371
  }, [target.url, fetchDeployments]);
371
372
  const cancel = (0, import_react2.useCallback)(async () => {
372
373
  if (!latest?.uid) return;
@@ -433,7 +434,7 @@ function DeployItem({ target, token, onDelete, onEdit }) {
433
434
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { width: "12", height: "12", viewBox: "0 0 16 16", fill: "currentColor", "aria-hidden": "true", style: { marginLeft: "-0.1em", opacity: 0.5 }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M5 3.25a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0zm0 2.122a2.25 2.25 0 1 0-1.5 0v.878A2.25 2.25 0 0 0 5.75 8.5h1.5v2.128a2.251 2.251 0 1 0 1.5 0V8.5h1.5a2.25 2.25 0 0 0 2.25-2.25v-.878a2.25 2.25 0 1 0-1.5 0v.878a.75.75 0 0 1-.75.75h-4.5A.75.75 0 0 1 5 6.25v-.878zm3.75 7.378a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0zm3-8.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0z" }) })
434
435
  ] }) }),
435
436
  token && !loadingInitial && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
436
- triggering ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Badge, { tone: "caution", padding: 2, children: "Triggering\u2026" }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StatusBadge, { state: latest?.state, showSpinner: true }),
437
+ triggering ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Badge, { tone: "caution", padding: 2, children: "Triggering\u2026" }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StatusBadge, { state: latest?.state }),
437
438
  isActiveState(latest?.state) && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
438
439
  import_ui3.Button,
439
440
  {
@@ -547,6 +548,11 @@ function DeployItem({ target, token, onDelete, onEdit }) {
547
548
  "by ",
548
549
  creator
549
550
  ] }),
551
+ latest?.state === "READY" && latest.ready && latest.created && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Text, { size: 1, muted: true, children: [
552
+ "Took ",
553
+ formatDuration(Math.floor((latest.ready - latest.created) / 1e3)),
554
+ " to build"
555
+ ] }),
550
556
  latest?.url && latest.state === "READY" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
551
557
  import_ui3.Tooltip,
552
558
  {
package/dist/index.mjs CHANGED
@@ -21,7 +21,6 @@ import { TokenIcon, TrashIcon as TrashIcon2, WarningOutlineIcon as WarningOutlin
21
21
 
22
22
  // src/components/DeployItem.tsx
23
23
  import { useState as useState2, useEffect as useEffect2, useCallback as useCallback2, useRef } from "react";
24
- import { flushSync } from "react-dom";
25
24
  import {
26
25
  Card as Card2,
27
26
  Box as Box2,
@@ -379,16 +378,18 @@ function DeployItem({ target, token, onDelete, onEdit }) {
379
378
  if (timerRef.current) clearInterval(timerRef.current);
380
379
  };
381
380
  }, [isActive, latest?.created]);
382
- const deploy = useCallback2(async () => {
381
+ const deploy = useCallback2(() => {
383
382
  setDeployError(null);
384
- flushSync(() => setTriggering(true));
385
- try {
386
- await triggerDeploy(target.url);
387
- setTimeout(fetchDeployments, 2e3);
388
- } catch (err) {
389
- setTriggering(false);
390
- setDeployError(err instanceof Error ? err.message : "Deploy failed");
391
- }
383
+ setTriggering(true);
384
+ void (async () => {
385
+ try {
386
+ await triggerDeploy(target.url);
387
+ setTimeout(fetchDeployments, 2e3);
388
+ } catch (err) {
389
+ setTriggering(false);
390
+ setDeployError(err instanceof Error ? err.message : "Deploy failed");
391
+ }
392
+ })();
392
393
  }, [target.url, fetchDeployments]);
393
394
  const cancel = useCallback2(async () => {
394
395
  if (!latest?.uid) return;
@@ -455,7 +456,7 @@ function DeployItem({ target, token, onDelete, onEdit }) {
455
456
  /* @__PURE__ */ jsx3("svg", { width: "12", height: "12", viewBox: "0 0 16 16", fill: "currentColor", "aria-hidden": "true", style: { marginLeft: "-0.1em", opacity: 0.5 }, children: /* @__PURE__ */ jsx3("path", { d: "M5 3.25a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0zm0 2.122a2.25 2.25 0 1 0-1.5 0v.878A2.25 2.25 0 0 0 5.75 8.5h1.5v2.128a2.251 2.251 0 1 0 1.5 0V8.5h1.5a2.25 2.25 0 0 0 2.25-2.25v-.878a2.25 2.25 0 1 0-1.5 0v.878a.75.75 0 0 1-.75.75h-4.5A.75.75 0 0 1 5 6.25v-.878zm3.75 7.378a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0zm3-8.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0z" }) })
456
457
  ] }) }),
457
458
  token && !loadingInitial && /* @__PURE__ */ jsxs3(Fragment, { children: [
458
- triggering ? /* @__PURE__ */ jsx3(Badge3, { tone: "caution", padding: 2, children: "Triggering\u2026" }) : /* @__PURE__ */ jsx3(StatusBadge, { state: latest?.state, showSpinner: true }),
459
+ triggering ? /* @__PURE__ */ jsx3(Badge3, { tone: "caution", padding: 2, children: "Triggering\u2026" }) : /* @__PURE__ */ jsx3(StatusBadge, { state: latest?.state }),
459
460
  isActiveState(latest?.state) && /* @__PURE__ */ jsx3(
460
461
  Button2,
461
462
  {
@@ -569,6 +570,11 @@ function DeployItem({ target, token, onDelete, onEdit }) {
569
570
  "by ",
570
571
  creator
571
572
  ] }),
573
+ latest?.state === "READY" && latest.ready && latest.created && /* @__PURE__ */ jsxs3(Text2, { size: 1, muted: true, children: [
574
+ "Took ",
575
+ formatDuration(Math.floor((latest.ready - latest.created) / 1e3)),
576
+ " to build"
577
+ ] }),
572
578
  latest?.url && latest.state === "READY" && /* @__PURE__ */ jsx3(Fragment, { children: /* @__PURE__ */ jsx3(
573
579
  Tooltip,
574
580
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liiift-studio/deploy-vercel-from-sanity",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Sanity Studio plugin — trigger and monitor Vercel deployments with full status, history, and build logs. Supports v3, v4, and v5.",
5
5
  "license": "MIT",
6
6
  "author": "Liiift Studio",
@@ -1,6 +1,5 @@
1
1
  // Per-deploy-target card — shows status, build timer, history, cancel, deploy, copy URL, and error logs
2
2
  import { useState, useEffect, useCallback, useRef } from 'react'
3
- import { flushSync } from 'react-dom'
4
3
  import {
5
4
  Card, Box, Stack, Flex, Text, Button, Tooltip, Badge, Spinner,
6
5
  MenuButton, Menu, MenuItem, Code, useToast,
@@ -111,16 +110,18 @@ export function DeployItem({ target, token, onDelete, onEdit }: DeployItemProps)
111
110
  }, [isActive, latest?.created])
112
111
 
113
112
  // ── Actions ───────────────────────────────────────────────────────────────
114
- const deploy = useCallback(async () => {
113
+ const deploy = useCallback(() => {
115
114
  setDeployError(null)
116
- flushSync(() => setTriggering(true))
117
- try {
118
- await triggerDeploy(target.url)
119
- setTimeout(fetchDeployments, 2000)
120
- } catch (err) {
121
- setTriggering(false)
122
- setDeployError(err instanceof Error ? err.message : 'Deploy failed')
123
- }
115
+ setTriggering(true)
116
+ void (async () => {
117
+ try {
118
+ await triggerDeploy(target.url)
119
+ setTimeout(fetchDeployments, 2000)
120
+ } catch (err) {
121
+ setTriggering(false)
122
+ setDeployError(err instanceof Error ? err.message : 'Deploy failed')
123
+ }
124
+ })()
124
125
  }, [target.url, fetchDeployments])
125
126
 
126
127
  const cancel = useCallback(async () => {
@@ -217,7 +218,7 @@ export function DeployItem({ target, token, onDelete, onEdit }: DeployItemProps)
217
218
  {triggering ? (
218
219
  <Badge tone="caution" padding={2}>Triggering…</Badge>
219
220
  ) : (
220
- <StatusBadge state={latest?.state} showSpinner />
221
+ <StatusBadge state={latest?.state} />
221
222
  )}
222
223
  {isActiveState(latest?.state) && (
223
224
  <Button
@@ -355,6 +356,11 @@ export function DeployItem({ target, token, onDelete, onEdit }: DeployItemProps)
355
356
  {/* Creator */}
356
357
  {creator && <Text size={1} muted>by {creator}</Text>}
357
358
 
359
+ {/* Build duration — only shown when READY and ready timestamp is available */}
360
+ {latest?.state === 'READY' && latest.ready && latest.created && (
361
+ <Text size={1} muted>Took {formatDuration(Math.floor((latest.ready - latest.created) / 1000))} to build</Text>
362
+ )}
363
+
358
364
  {/* Visit link + copy URL */}
359
365
  {latest?.url && latest.state === 'READY' && (
360
366
  <>
package/src/types.ts CHANGED
@@ -28,8 +28,10 @@ export interface VercelDeployment {
28
28
  /** Preview hostname, e.g. my-project-abc123.vercel.app */
29
29
  url: string
30
30
  state: VercelDeployState
31
- /** Unix ms timestamp */
31
+ /** Unix ms timestamp — when the deployment was created */
32
32
  created: number
33
+ /** Unix ms timestamp — when the deployment became ready */
34
+ ready?: number
33
35
  /** Link to the Vercel dashboard page for this deployment */
34
36
  inspectorUrl?: string
35
37
  creator?: {