@liiift-studio/deploy-vercel-from-sanity 1.0.2 → 1.0.4
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.js +26 -15
- package/dist/index.mjs +26 -15
- package/package.json +1 -1
- package/src/components/DeployItem.tsx +26 -14
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
|
|
|
@@ -289,6 +288,7 @@ function DeployItem({ target, token, onDelete, onEdit }) {
|
|
|
289
288
|
const [deployments, setDeployments] = (0, import_react2.useState)([]);
|
|
290
289
|
const [loadingInitial, setLoadingInitial] = (0, import_react2.useState)(true);
|
|
291
290
|
const [triggering, setTriggering] = (0, import_react2.useState)(false);
|
|
291
|
+
const [clicked, setClicked] = (0, import_react2.useState)(false);
|
|
292
292
|
const [canceling, setCanceling] = (0, import_react2.useState)(false);
|
|
293
293
|
const [deployError, setDeployError] = (0, import_react2.useState)(null);
|
|
294
294
|
const [showHistory, setShowHistory] = (0, import_react2.useState)(false);
|
|
@@ -321,6 +321,9 @@ function DeployItem({ target, token, onDelete, onEdit }) {
|
|
|
321
321
|
(0, import_react2.useEffect)(() => {
|
|
322
322
|
if (triggering && latest && latest.state !== void 0) setTriggering(false);
|
|
323
323
|
}, [triggering, latest]);
|
|
324
|
+
(0, import_react2.useEffect)(() => {
|
|
325
|
+
if (triggering) setClicked(false);
|
|
326
|
+
}, [triggering]);
|
|
324
327
|
const prevStateRef = (0, import_react2.useRef)(void 0);
|
|
325
328
|
(0, import_react2.useEffect)(() => {
|
|
326
329
|
const current = latest?.state;
|
|
@@ -357,16 +360,20 @@ function DeployItem({ target, token, onDelete, onEdit }) {
|
|
|
357
360
|
if (timerRef.current) clearInterval(timerRef.current);
|
|
358
361
|
};
|
|
359
362
|
}, [isActive, latest?.created]);
|
|
360
|
-
const deploy = (0, import_react2.useCallback)(
|
|
363
|
+
const deploy = (0, import_react2.useCallback)(() => {
|
|
361
364
|
setDeployError(null);
|
|
362
|
-
(
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
365
|
+
setClicked(true);
|
|
366
|
+
setTriggering(true);
|
|
367
|
+
void (async () => {
|
|
368
|
+
try {
|
|
369
|
+
await triggerDeploy(target.url);
|
|
370
|
+
setTimeout(fetchDeployments, 2e3);
|
|
371
|
+
} catch (err) {
|
|
372
|
+
setTriggering(false);
|
|
373
|
+
setClicked(false);
|
|
374
|
+
setDeployError(err instanceof Error ? err.message : "Deploy failed");
|
|
375
|
+
}
|
|
376
|
+
})();
|
|
370
377
|
}, [target.url, fetchDeployments]);
|
|
371
378
|
const cancel = (0, import_react2.useCallback)(async () => {
|
|
372
379
|
if (!latest?.uid) return;
|
|
@@ -433,7 +440,7 @@ function DeployItem({ target, token, onDelete, onEdit }) {
|
|
|
433
440
|
/* @__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
441
|
] }) }),
|
|
435
442
|
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
|
|
443
|
+
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
444
|
isActiveState(latest?.state) && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
438
445
|
import_ui3.Button,
|
|
439
446
|
{
|
|
@@ -446,7 +453,10 @@ function DeployItem({ target, token, onDelete, onEdit }) {
|
|
|
446
453
|
style: { cursor: "pointer" }
|
|
447
454
|
}
|
|
448
455
|
),
|
|
449
|
-
isActive && elapsed > 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.
|
|
456
|
+
isActive && elapsed > 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { align: "center", gap: 1, children: [
|
|
457
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Spinner, { muted: true, style: { marginLeft: 4 } }),
|
|
458
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 1, muted: true, children: formatDuration(elapsed) })
|
|
459
|
+
] }) : !isActive && deployedAt ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 1, muted: true, children: deployedAt }) : null
|
|
450
460
|
] })
|
|
451
461
|
] }),
|
|
452
462
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
@@ -545,8 +555,9 @@ function DeployItem({ target, token, onDelete, onEdit }) {
|
|
|
545
555
|
creator
|
|
546
556
|
] }),
|
|
547
557
|
latest?.state === "READY" && latest.ready && latest.created && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Text, { size: 1, muted: true, children: [
|
|
548
|
-
"
|
|
549
|
-
formatDuration(Math.floor((latest.ready - latest.created) / 1e3))
|
|
558
|
+
"Took ",
|
|
559
|
+
formatDuration(Math.floor((latest.ready - latest.created) / 1e3)),
|
|
560
|
+
" to build"
|
|
550
561
|
] }),
|
|
551
562
|
latest?.url && latest.state === "READY" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
552
563
|
import_ui3.Tooltip,
|
|
@@ -689,7 +700,7 @@ function DeployItem({ target, token, onDelete, onEdit }) {
|
|
|
689
700
|
text: "Deploy",
|
|
690
701
|
tone: "primary",
|
|
691
702
|
loading: triggering,
|
|
692
|
-
disabled: isActive,
|
|
703
|
+
disabled: isActive || clicked,
|
|
693
704
|
onClick: deploy,
|
|
694
705
|
style: {
|
|
695
706
|
flex: 1,
|
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,
|
|
@@ -311,6 +310,7 @@ function DeployItem({ target, token, onDelete, onEdit }) {
|
|
|
311
310
|
const [deployments, setDeployments] = useState2([]);
|
|
312
311
|
const [loadingInitial, setLoadingInitial] = useState2(true);
|
|
313
312
|
const [triggering, setTriggering] = useState2(false);
|
|
313
|
+
const [clicked, setClicked] = useState2(false);
|
|
314
314
|
const [canceling, setCanceling] = useState2(false);
|
|
315
315
|
const [deployError, setDeployError] = useState2(null);
|
|
316
316
|
const [showHistory, setShowHistory] = useState2(false);
|
|
@@ -343,6 +343,9 @@ function DeployItem({ target, token, onDelete, onEdit }) {
|
|
|
343
343
|
useEffect2(() => {
|
|
344
344
|
if (triggering && latest && latest.state !== void 0) setTriggering(false);
|
|
345
345
|
}, [triggering, latest]);
|
|
346
|
+
useEffect2(() => {
|
|
347
|
+
if (triggering) setClicked(false);
|
|
348
|
+
}, [triggering]);
|
|
346
349
|
const prevStateRef = useRef(void 0);
|
|
347
350
|
useEffect2(() => {
|
|
348
351
|
const current = latest?.state;
|
|
@@ -379,16 +382,20 @@ function DeployItem({ target, token, onDelete, onEdit }) {
|
|
|
379
382
|
if (timerRef.current) clearInterval(timerRef.current);
|
|
380
383
|
};
|
|
381
384
|
}, [isActive, latest?.created]);
|
|
382
|
-
const deploy = useCallback2(
|
|
385
|
+
const deploy = useCallback2(() => {
|
|
383
386
|
setDeployError(null);
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
387
|
+
setClicked(true);
|
|
388
|
+
setTriggering(true);
|
|
389
|
+
void (async () => {
|
|
390
|
+
try {
|
|
391
|
+
await triggerDeploy(target.url);
|
|
392
|
+
setTimeout(fetchDeployments, 2e3);
|
|
393
|
+
} catch (err) {
|
|
394
|
+
setTriggering(false);
|
|
395
|
+
setClicked(false);
|
|
396
|
+
setDeployError(err instanceof Error ? err.message : "Deploy failed");
|
|
397
|
+
}
|
|
398
|
+
})();
|
|
392
399
|
}, [target.url, fetchDeployments]);
|
|
393
400
|
const cancel = useCallback2(async () => {
|
|
394
401
|
if (!latest?.uid) return;
|
|
@@ -455,7 +462,7 @@ function DeployItem({ target, token, onDelete, onEdit }) {
|
|
|
455
462
|
/* @__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
463
|
] }) }),
|
|
457
464
|
token && !loadingInitial && /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
458
|
-
triggering ? /* @__PURE__ */ jsx3(Badge3, { tone: "caution", padding: 2, children: "Triggering\u2026" }) : /* @__PURE__ */ jsx3(StatusBadge, { state: latest?.state
|
|
465
|
+
triggering ? /* @__PURE__ */ jsx3(Badge3, { tone: "caution", padding: 2, children: "Triggering\u2026" }) : /* @__PURE__ */ jsx3(StatusBadge, { state: latest?.state }),
|
|
459
466
|
isActiveState(latest?.state) && /* @__PURE__ */ jsx3(
|
|
460
467
|
Button2,
|
|
461
468
|
{
|
|
@@ -468,7 +475,10 @@ function DeployItem({ target, token, onDelete, onEdit }) {
|
|
|
468
475
|
style: { cursor: "pointer" }
|
|
469
476
|
}
|
|
470
477
|
),
|
|
471
|
-
isActive && elapsed > 0 ? /* @__PURE__ */
|
|
478
|
+
isActive && elapsed > 0 ? /* @__PURE__ */ jsxs3(Flex3, { align: "center", gap: 1, children: [
|
|
479
|
+
/* @__PURE__ */ jsx3(Spinner3, { muted: true, style: { marginLeft: 4 } }),
|
|
480
|
+
/* @__PURE__ */ jsx3(Text2, { size: 1, muted: true, children: formatDuration(elapsed) })
|
|
481
|
+
] }) : !isActive && deployedAt ? /* @__PURE__ */ jsx3(Text2, { size: 1, muted: true, children: deployedAt }) : null
|
|
472
482
|
] })
|
|
473
483
|
] }),
|
|
474
484
|
/* @__PURE__ */ jsx3(
|
|
@@ -567,8 +577,9 @@ function DeployItem({ target, token, onDelete, onEdit }) {
|
|
|
567
577
|
creator
|
|
568
578
|
] }),
|
|
569
579
|
latest?.state === "READY" && latest.ready && latest.created && /* @__PURE__ */ jsxs3(Text2, { size: 1, muted: true, children: [
|
|
570
|
-
"
|
|
571
|
-
formatDuration(Math.floor((latest.ready - latest.created) / 1e3))
|
|
580
|
+
"Took ",
|
|
581
|
+
formatDuration(Math.floor((latest.ready - latest.created) / 1e3)),
|
|
582
|
+
" to build"
|
|
572
583
|
] }),
|
|
573
584
|
latest?.url && latest.state === "READY" && /* @__PURE__ */ jsx3(Fragment, { children: /* @__PURE__ */ jsx3(
|
|
574
585
|
Tooltip,
|
|
@@ -711,7 +722,7 @@ function DeployItem({ target, token, onDelete, onEdit }) {
|
|
|
711
722
|
text: "Deploy",
|
|
712
723
|
tone: "primary",
|
|
713
724
|
loading: triggering,
|
|
714
|
-
disabled: isActive,
|
|
725
|
+
disabled: isActive || clicked,
|
|
715
726
|
onClick: deploy,
|
|
716
727
|
style: {
|
|
717
728
|
flex: 1,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@liiift-studio/deploy-vercel-from-sanity",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
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,
|
|
@@ -32,6 +31,7 @@ export function DeployItem({ target, token, onDelete, onEdit }: DeployItemProps)
|
|
|
32
31
|
const [deployments, setDeployments] = useState<VercelDeployment[]>([])
|
|
33
32
|
const [loadingInitial, setLoadingInitial] = useState(true)
|
|
34
33
|
const [triggering, setTriggering] = useState(false)
|
|
34
|
+
const [clicked, setClicked] = useState(false)
|
|
35
35
|
const [canceling, setCanceling] = useState(false)
|
|
36
36
|
const [deployError, setDeployError] = useState<string | null>(null)
|
|
37
37
|
const [showHistory, setShowHistory] = useState(false)
|
|
@@ -71,6 +71,11 @@ export function DeployItem({ target, token, onDelete, onEdit }: DeployItemProps)
|
|
|
71
71
|
if (triggering && latest && latest.state !== undefined) setTriggering(false)
|
|
72
72
|
}, [triggering, latest])
|
|
73
73
|
|
|
74
|
+
// Clear clicked once triggering has propagated — loading animation takes over
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
if (triggering) setClicked(false)
|
|
77
|
+
}, [triggering])
|
|
78
|
+
|
|
74
79
|
// ── Deploy-complete toast ─────────────────────────────────────────────────
|
|
75
80
|
const prevStateRef = useRef<string | undefined>(undefined)
|
|
76
81
|
useEffect(() => {
|
|
@@ -111,16 +116,20 @@ export function DeployItem({ target, token, onDelete, onEdit }: DeployItemProps)
|
|
|
111
116
|
}, [isActive, latest?.created])
|
|
112
117
|
|
|
113
118
|
// ── Actions ───────────────────────────────────────────────────────────────
|
|
114
|
-
const deploy = useCallback(
|
|
119
|
+
const deploy = useCallback(() => {
|
|
115
120
|
setDeployError(null)
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
121
|
+
setClicked(true)
|
|
122
|
+
setTriggering(true)
|
|
123
|
+
void (async () => {
|
|
124
|
+
try {
|
|
125
|
+
await triggerDeploy(target.url)
|
|
126
|
+
setTimeout(fetchDeployments, 2000)
|
|
127
|
+
} catch (err) {
|
|
128
|
+
setTriggering(false)
|
|
129
|
+
setClicked(false)
|
|
130
|
+
setDeployError(err instanceof Error ? err.message : 'Deploy failed')
|
|
131
|
+
}
|
|
132
|
+
})()
|
|
124
133
|
}, [target.url, fetchDeployments])
|
|
125
134
|
|
|
126
135
|
const cancel = useCallback(async () => {
|
|
@@ -217,7 +226,7 @@ export function DeployItem({ target, token, onDelete, onEdit }: DeployItemProps)
|
|
|
217
226
|
{triggering ? (
|
|
218
227
|
<Badge tone="caution" padding={2}>Triggering…</Badge>
|
|
219
228
|
) : (
|
|
220
|
-
<StatusBadge state={latest?.state}
|
|
229
|
+
<StatusBadge state={latest?.state} />
|
|
221
230
|
)}
|
|
222
231
|
{isActiveState(latest?.state) && (
|
|
223
232
|
<Button
|
|
@@ -231,7 +240,10 @@ export function DeployItem({ target, token, onDelete, onEdit }: DeployItemProps)
|
|
|
231
240
|
/>
|
|
232
241
|
)}
|
|
233
242
|
{isActive && elapsed > 0 ? (
|
|
234
|
-
<
|
|
243
|
+
<Flex align="center" gap={1}>
|
|
244
|
+
<Spinner muted style={{ marginLeft: 4 }} />
|
|
245
|
+
<Text size={1} muted>{formatDuration(elapsed)}</Text>
|
|
246
|
+
</Flex>
|
|
235
247
|
) : (!isActive && deployedAt) ? (
|
|
236
248
|
<Text size={1} muted>{deployedAt}</Text>
|
|
237
249
|
) : null}
|
|
@@ -354,7 +366,7 @@ export function DeployItem({ target, token, onDelete, onEdit }: DeployItemProps)
|
|
|
354
366
|
|
|
355
367
|
{/* Build duration — only shown when READY and ready timestamp is available */}
|
|
356
368
|
{latest?.state === 'READY' && latest.ready && latest.created && (
|
|
357
|
-
<Text size={1} muted
|
|
369
|
+
<Text size={1} muted>Took {formatDuration(Math.floor((latest.ready - latest.created) / 1000))} to build</Text>
|
|
358
370
|
)}
|
|
359
371
|
|
|
360
372
|
{/* Visit link + copy URL */}
|
|
@@ -556,7 +568,7 @@ export function DeployItem({ target, token, onDelete, onEdit }: DeployItemProps)
|
|
|
556
568
|
text="Deploy"
|
|
557
569
|
tone="primary"
|
|
558
570
|
loading={triggering}
|
|
559
|
-
disabled={isActive}
|
|
571
|
+
disabled={isActive || clicked}
|
|
560
572
|
onClick={deploy}
|
|
561
573
|
style={{
|
|
562
574
|
flex: 1,
|