sanity-plugin-dashboard-widget-vercel 3.1.2 → 3.1.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/lib/index.mjs CHANGED
@@ -1,18 +1,17 @@
1
1
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
2
  import { LinkIcon, UploadIcon, EditIcon, ErrorOutlineIcon, AddIcon } from "@sanity/icons";
3
3
  import { useTheme, Box, Label, Flex, Text, Stack, useToast, Button, Tooltip, Inline, TextInput, Dialog, ToastProvider, Card } from "@sanity/ui";
4
- import { useMachine } from "@xstate/react";
4
+ import { useMachine, useActor } from "@xstate/react";
5
5
  import { useQuery, QueryClient, QueryClientProvider } from "@tanstack/react-query";
6
- import { Machine, assign } from "xstate";
7
- import { useRef, useMemo, useEffect, forwardRef } from "react";
6
+ import { setup, fromPromise, assign, assertEvent, toPromise } from "xstate";
7
+ import { useRef, useEffect, forwardRef } from "react";
8
8
  import useDeepCompareEffect from "use-deep-compare-effect";
9
9
  import hash from "object-hash";
10
- import fetch from "unfetch";
11
10
  import ReactTimeAgo from "react-time-ago";
12
11
  import { yupResolver } from "@hookform/resolvers/yup";
13
- import { uuid } from "@sanity/uuid";
14
12
  import { useForm } from "react-hook-form";
15
13
  import * as yup from "yup";
14
+ import { uuid } from "@sanity/uuid";
16
15
  import { styled } from "styled-components";
17
16
  import { useClient } from "sanity";
18
17
  import TimeAgo from "javascript-time-ago";
@@ -23,77 +22,99 @@ const API_ENDPOINT_DEPLOYMENTS = "https://api.vercel.com/v5/now/deployments", AP
23
22
  ERROR: "#ff0000",
24
23
  READY: "#50e3c2",
25
24
  QUEUED: "#333"
26
- }, WIDGET_NAME = "Vercel (dashboard)", Z_INDEX_DIALOG = 600001, Z_INDEX_TOAST_PROVIDER = 600002, StateDebug = (props) => null, sortByTargetName = (items) => items.sort((a, b) => a.name > b.name ? 1 : a.name < b.name ? -1 : 0), deploymentTargetListMachine = () => Machine(
27
- {
28
- context: {
29
- message: "",
30
- results: []
25
+ }, WIDGET_NAME = "Vercel (dashboard)", Z_INDEX_DIALOG = 600001, Z_INDEX_TOAST_PROVIDER = 600002, StateDebug = (props) => null, sortByTargetName = (items) => items.sort((a, b) => a.name > b.name ? 1 : a.name < b.name ? -1 : 0), deploymentTargetListMachine = setup({
26
+ types: {},
27
+ actions: {
28
+ targetCreate: assign({
29
+ results: ({ context, event }) => (assertEvent(event, "CREATE"), sortByTargetName([...context.results, event.deploymentTarget]))
30
+ }),
31
+ targetDelete: assign({
32
+ results: ({ context, event }) => (assertEvent(event, "DELETE"), context.results.filter((target) => target._id !== event.id))
33
+ }),
34
+ targetUpdate: assign({
35
+ results: ({ context, event }) => {
36
+ assertEvent(event, "UPDATE");
37
+ const { deploymentTarget } = event, index = context.results.findIndex((target) => target._id === deploymentTarget._id), updatedResults = Object.assign([], context.results, {
38
+ [index]: deploymentTarget
39
+ });
40
+ return sortByTargetName(updatedResults);
41
+ }
42
+ })
43
+ },
44
+ guards: {
45
+ hasData: ({ context }) => context?.results?.length > 0,
46
+ hasNoData: ({ context }) => context?.results?.length === 0
47
+ },
48
+ actors: {
49
+ "fetch data": fromPromise(
50
+ ({ input, signal }) => input.client.fetch(
51
+ "*[_type == $type] | order(name asc)",
52
+ {
53
+ type: DEPLOYMENT_TARGET_DOCUMENT_TYPE
54
+ },
55
+ { signal }
56
+ ).catch((error) => {
57
+ if (error instanceof Error && error.name === "AbortError")
58
+ return [];
59
+ throw console.error("Failed to fetch deployment targets", error), error;
60
+ })
61
+ )
62
+ }
63
+ }).createMachine({
64
+ /** @xstate-layout N4IgpgJg5mDOIC5QAoC2BDAxgCwJYDswBKAOgAcx8ICoBiCAe0JIIDcGBrMEgMzABccAEXT90AbQAMAXUSgyDWLn64mckAA9EAZkkBOEgHYAjAA5DAFgBsFgEwnJAVkMAaEAE9Ep4yUeT-klbGesbaoYaGAL6RbmhYeISkFFQ0tGAATukM6eQANqI82ai8AsKiEjLqCkoqakiaOvpGZpY29sZOrh6IxpYkFo5h2oaOpnqOxraSFtGxGDgExCTpYOgQ7rQAwgBKAKIAggAqu1Ky9dXKqvjqWggWHSS9eoaS9ibao6aObp4IVh8kL56OzGII2PT-WYgOILRLLVbrWhCXYAGV2x1OVUUlzqoFu90kRm8tlM2gsL1eJJ+iEGBj0gVsFm0YWmVkctihMISSxWaw2AFUAApCI4nSrnbG1a71fGSUz9WzBezTFWvb7dO5MkjjMITZykwxjTnzbmkXnrEgAV3wHHwDAA7vhaJiJTUrjces9fFZGc9TLYrGqA9SEM9CcT7sznH5HHpjfFFmaEe4rTa7Y7ncYzvJJe6ZZ7DN7fYaA0GrCHvD4xs4S+yPnGYtCTYn4XySPblNgRGJneKc27cQ0EI4BiQ2T77noAzXyxrTIESGFGd4rP9DONTPHYTzk+3OwxLfxu+he9mQBcpR7h6Px4ylWyIrPfl9bIvJhZJIYA-7zFZoo27QgOB1C5RMsQHaU8UQABaYIQ2gv9G1AuFkmofAoHAnFIKHOwQz0bRtUMcd-j8WwpnuLdTVbdZMMvfMEFsPQQxMeViQmZkLC+f0oiQ5s4XNFNrVtB1sIvPMoIQCIK1BIsmXXWxtFJcZKJbAS934Ltylo8ShysfDHl9PRxjlekrC6Z9BhIBk5MkXpzFBFT+N3DsNIPI8tNdLCr20L0Wmscw5V0e5pMJYwBiI8kwrDRC5gTOEeHQXBckgbTB1uZwQw6RwrEBd9bEcQZYzsRDoiAA */
65
+ context: ({ input }) => ({
66
+ client: input.client,
67
+ results: []
68
+ }),
69
+ initial: "pending",
70
+ states: {
71
+ pending: {
72
+ invoke: {
73
+ src: "fetch data",
74
+ id: "fetchData",
75
+ input: ({ context }) => ({ client: context.client }),
76
+ onDone: {
77
+ actions: assign({ results: ({ event }) => event.output }),
78
+ target: "ready"
79
+ },
80
+ onError: {
81
+ target: "failed"
82
+ }
83
+ }
31
84
  },
32
- initial: "pending",
33
- states: {
34
- pending: {
35
- invoke: {
36
- src: "fetchDataService",
37
- onDone: { actions: ["setResults"], target: "ready" },
38
- onError: { actions: ["setMessage"], target: "failed" }
85
+ ready: {
86
+ initial: "unknown",
87
+ on: {
88
+ CREATE: {
89
+ actions: "targetCreate"
90
+ },
91
+ DELETE: {
92
+ actions: "targetDelete"
93
+ },
94
+ UPDATE: {
95
+ actions: "targetUpdate"
39
96
  }
40
97
  },
41
- ready: {
42
- initial: "unknown",
43
- on: {
44
- CREATE: { actions: ["targetCreate"] },
45
- DELETE: { actions: ["targetDelete"] },
46
- UPDATE: { actions: ["targetUpdate"] }
98
+ states: {
99
+ unknown: {
100
+ always: [
101
+ { target: "withData", guard: "hasData" },
102
+ { target: "withoutData", guard: "hasNoData" }
103
+ ]
47
104
  },
48
- states: {
49
- unknown: {
50
- always: [
51
- { cond: "hasData", target: "withData" },
52
- { cond: "hasNoData", target: "withoutData" }
53
- ]
54
- },
55
- withData: {
56
- always: [{ cond: "hasNoData", target: "withoutData" }]
57
- },
58
- withoutData: {
59
- always: [{ cond: "hasData", target: "withData" }]
60
- }
105
+ withData: {
106
+ always: [{ target: "withoutData", guard: "hasNoData" }]
107
+ },
108
+ withoutData: {
109
+ always: [{ target: "withData", guard: "hasData" }]
61
110
  }
62
- },
63
- failed: {
64
- type: "final"
65
111
  }
66
- }
67
- },
68
- {
69
- actions: {
70
- setMessage: assign((_context, event) => ({
71
- message: event.data.details.description
72
- })),
73
- setResults: assign((_context, event) => ({
74
- results: event.data
75
- })),
76
- targetCreate: assign((context, event) => ({
77
- results: sortByTargetName([...context.results, event.deploymentTarget])
78
- })),
79
- targetDelete: assign((context, event) => ({
80
- results: context.results.filter((target) => target._id !== event.id)
81
- })),
82
- targetUpdate: assign((context, event) => {
83
- const { deploymentTarget } = event, index = context.results.findIndex((target) => target._id === deploymentTarget._id), updatedResults = Object.assign([], context.results, {
84
- [index]: event.deploymentTarget
85
- });
86
- return {
87
- results: sortByTargetName(updatedResults)
88
- };
89
- })
90
112
  },
91
- guards: {
92
- hasData: (context) => context?.results?.length > 0,
93
- hasNoData: (context) => context?.results?.length === 0
113
+ failed: {
114
+ type: "final"
94
115
  }
95
116
  }
96
- ), fetcher = (deploymentTarget) => async (url, extraParams) => {
117
+ }), fetcher = (deploymentTarget) => async (url, extraParams) => {
97
118
  const params = new URLSearchParams();
98
119
  if (params.set("projectId", deploymentTarget.projectId), deploymentTarget.teamId && params.set("teamId", deploymentTarget.teamId), extraParams)
99
120
  for (const [k, v] of extraParams.entries())
@@ -160,28 +181,43 @@ const API_ENDPOINT_DEPLOYMENTS = "https://api.vercel.com/v5/now/deployments", AP
160
181
  isSuccess: aliasesIsSuccess && deploymentsIsSuccess,
161
182
  refetch
162
183
  };
163
- }, refreshMachine = Machine({
184
+ }, refreshMachine = setup({
185
+ types: {
186
+ events: {}
187
+ }
188
+ }).createMachine({
189
+ /** @xstate-layout N4IgpgJg5mDOIC5QAoC2BDAxgCwJYDswBKAOlwgBswBiAJQFEAxBgZQAkBtABgF1FQADgHtYuAC64h+fiAAeiAIwAmAGwkuGrkoAsAZhVKlAVm0KAHABoQAT0QBOJSRN27XFXaMmz2twF9fVmhYeISkAE5gAGYRsCFQ1PS0tADytNx8SCDCohJSMvIIPnYkxhpKXGZ22kY6xla2CAq6CiQudgDsRnYqKroVfe3+gRg4BMQkEdFwcXRMrGz0ACLpMtniktKZBUUlRmUVVTXadTaISrqObUY97QodvWa6QyBBo6ETUTHYkLPM9OwrTJrXKbUDbJTFLjtMzmWraOx3doqeqKMyOeHdXp3BTHXTVZ6vELjMBhMJCMK-eaAwQidZ5LaIY6Q6Gw47wxHI04IGEkDFma5NbTtY7ufwBED4IQQOAyQljIirWkg-KIAC0nIa6oJIyJpHIVEVOQ2KsKShRCDsunUGLcHi8PhU2uC8o+U1iBCghrpoLkZ2uTk0XCq7SRRl0Zg19itXHhIZ85lMEaUTre40mX0gXuVDIQnmKRhZKk6PmaVXN2PUaLsZhj2hUOJU-JTupIJLJYSzxpzeacheLXFL2nNrkrfW8SKFnhDYt8QA */
164
190
  initial: "idle",
165
191
  states: {
166
192
  idle: {
167
193
  on: {
168
- REFRESH: "refreshing"
194
+ REFRESH: {
195
+ target: "refreshing"
196
+ }
169
197
  }
170
198
  },
171
199
  refreshing: {
172
200
  on: {
173
- ERROR: "error",
174
- REFRESHED: "refreshed"
201
+ ERROR: {
202
+ target: "error"
203
+ },
204
+ REFRESHED: {
205
+ target: "refreshed"
206
+ }
175
207
  }
176
208
  },
177
209
  refreshed: {
178
210
  on: {
179
- REFRESH: "refreshing"
211
+ REFRESH: {
212
+ target: "refreshing"
213
+ }
180
214
  }
181
215
  },
182
216
  error: {
183
217
  on: {
184
- REFRESH: "refreshing"
218
+ REFRESH: {
219
+ target: "refreshing"
220
+ }
185
221
  }
186
222
  }
187
223
  }
@@ -302,88 +338,98 @@ const TableCell = (props) => {
302
338
  }
303
339
  ) }) })
304
340
  ] });
305
- }, deployMachine = (deployHook) => Machine(
306
- // Machine
307
- {
308
- id: "deploy",
309
- initial: "idle",
310
- context: {
311
- disabled: !1,
312
- feedback: void 0,
313
- label: void 0,
314
- error: void 0
315
- },
316
- states: {
317
- idle: {
318
- entry: assign({
319
- feedback: () => {
320
- },
321
- label: () => "Deploy"
322
- }),
323
- on: {
324
- DEPLOY: "deploying"
341
+ }, deployMachine = setup({
342
+ types: {
343
+ context: {},
344
+ events: {},
345
+ input: {}
346
+ },
347
+ actors: {
348
+ deploy: fromPromise(async ({ input, signal }) => {
349
+ try {
350
+ if (!input.deployHook)
351
+ throw new Error("No deployHook URL defined");
352
+ const res = await fetch(input.deployHook, { method: "POST", signal }), data = await res.json();
353
+ if (!res.ok)
354
+ throw (data?.error).message || res.statusText;
355
+ } catch (err) {
356
+ throw typeof err == "string" ? err : (console.error("Unable to deploy with error:", err), new Error("Please check the developer console for more information"));
357
+ }
358
+ })
359
+ }
360
+ }).createMachine({
361
+ /** @xstate-layout N4IgpgJg5mDOIC5QTABwDYHsCeA6AlhOmAMQAiAogAoAyA8gJoDaADALqKiqaz4Au+TADtOIAB6IATCxa4AnADYAHAHYArArUslAZjksNAGhDZEARk3yVmhSxVyHC-QBYAvq+MoMOXF6zZ8ISgSCGEwAiEAN0wAa3C-HwSAoIRA6IBjAEMBYVY2PNFuXhyRJHFENTMzXElFJSUzNTVnWx0FY1MESXVcZzUdM2k1OTUVBoV3TzR-X2mcQOCwACclzCXcDGyAMzWAW1nvPCSF1KjMLJK8grKi-kFS0AkESura5QamlpY2jvMB+QcDkqLH0wxYEw8ICSuFgAFd0uk4LByNR6Mx2IUeHdhKIns1ZN9BtYQVpRnJfl1JM55P1BnY1Ep9CpGpMoXM8MtVksUbRGNcuFiSriKs4CQNurYRgZ7BSGr1ASNupIzEo+kp3JChJgUPAyklMcV7sKEABadomRAmtQAhW2wE6VnQwjEA3Yh7lBDOSQUsxeqyaPoWYbWFSO9kHfwLV1CspPHSSHQ1ZyA1UKJzJlQ+iz+5oKewKWrfNyQ6FwhFI6NG2OINOSXDiypKAxtMyZi1dEE1Qk6L0FpTSUMl8OctaVnHVhC1+uDRvNhStin6XDaHQ9liSXTJiUa1xAA */
362
+ id: "deploy",
363
+ initial: "idle",
364
+ context: ({ input }) => ({
365
+ disabled: !1,
366
+ feedback: void 0,
367
+ label: void 0,
368
+ error: void 0,
369
+ deployHook: input.deployHook
370
+ }),
371
+ states: {
372
+ idle: {
373
+ entry: assign({
374
+ feedback: () => {
375
+ },
376
+ label: () => "Deploy"
377
+ }),
378
+ on: {
379
+ DEPLOY: {
380
+ target: "deploying"
325
381
  }
326
- },
327
- deploying: {
328
- entry: assign({
329
- disabled: () => !0,
330
- label: () => "Deploying"
331
- }),
332
- exit: assign({
333
- disabled: () => !1,
334
- label: () => "Deploy"
335
- }),
336
- invoke: {
337
- onDone: {
338
- target: "success"
339
- },
340
- onError: {
341
- target: "error",
342
- actions: assign({
343
- error: (_context, event) => event.data
344
- })
345
- },
346
- src: "deploy"
382
+ }
383
+ },
384
+ deploying: {
385
+ entry: assign({
386
+ disabled: () => !0,
387
+ label: () => "Deploying"
388
+ }),
389
+ exit: assign({
390
+ disabled: () => !1,
391
+ label: () => "Deploy"
392
+ }),
393
+ invoke: {
394
+ src: "deploy",
395
+ input: ({ context }) => ({ deployHook: context.deployHook }),
396
+ onDone: {
397
+ target: "success"
398
+ },
399
+ onError: {
400
+ target: "error",
401
+ actions: assign({
402
+ error: ({ event }) => "error" in event ? event.error : "Unknown error"
403
+ })
347
404
  }
348
- },
349
- success: {
350
- entry: [assign({ feedback: () => "Succesfully started!" })],
351
- exit: assign({
352
- feedback: () => {
353
- }
354
- }),
355
- on: {
356
- DEPLOY: "deploying"
405
+ }
406
+ },
407
+ success: {
408
+ entry: assign({
409
+ feedback: () => "Successfully started!"
410
+ }),
411
+ exit: assign({
412
+ feedback: () => {
357
413
  }
358
- },
359
- error: {
360
- on: {
361
- DEPLOY: "deploying"
414
+ }),
415
+ on: {
416
+ DEPLOY: {
417
+ target: "deploying"
362
418
  }
363
419
  }
364
- }
365
- },
366
- // Config
367
- {
368
- services: {
369
- deploy: () => new Promise(async (resolve, reject) => {
370
- try {
371
- if (!deployHook)
372
- return reject(new Error("No deployHook URL defined"));
373
- const res = await fetch(deployHook, { method: "POST" }), data = await res.json();
374
- if (!res.ok) {
375
- const errorMessage = (data?.error).message || res.statusText;
376
- return reject(errorMessage);
377
- }
378
- return resolve();
379
- } catch (err) {
380
- return console.error("Unable to deploy with error:", err), reject(new Error("Please check the developer console for more information"));
420
+ },
421
+ error: {
422
+ on: {
423
+ DEPLOY: {
424
+ target: "deploying"
381
425
  }
382
- })
426
+ }
383
427
  }
384
428
  }
385
- ), DeployButton = (props) => {
386
- const { deployHook, onDeploySuccess, targetName } = props, machine = useMemo(() => deployMachine(deployHook), [deployHook]), [deployState, deployStateTransition, deployStateInterpreter] = useMachine(machine), toast = useToast(), isError = deployState.matches("error"), isSuccess = deployState.matches("success"), handleDeploy = () => {
429
+ }), DeployButton = (props) => {
430
+ const { deployHook, onDeploySuccess, targetName } = props, [deployState, deployStateTransition, deployStateInterpreter] = useMachine(deployMachine, {
431
+ input: { deployHook }
432
+ }), toast = useToast(), isError = deployState.matches("error"), isSuccess = deployState.matches("success"), handleDeploy = () => {
387
433
  deployStateTransition({ type: "DEPLOY" });
388
434
  };
389
435
  return useEffect(() => {
@@ -401,9 +447,10 @@ const TableCell = (props) => {
401
447
  title: WIDGET_NAME
402
448
  });
403
449
  }, [isError, isSuccess, toast, targetName, deployState.context.error]), useEffect(() => {
404
- deployStateInterpreter.onTransition((state) => {
450
+ const subscription = deployStateInterpreter.subscribe((state) => {
405
451
  state.value === "success" && onDeploySuccess && onDeploySuccess();
406
452
  });
453
+ return () => subscription.unsubscribe();
407
454
  }, [deployStateInterpreter, onDeploySuccess]), /* @__PURE__ */ jsxs(Box, { padding: 3, style: { position: "relative" }, children: [
408
455
  /* @__PURE__ */ jsx(StateDebug, { name: "Deploy", state: deployState }),
409
456
  /* @__PURE__ */ jsx(
@@ -548,88 +595,100 @@ const TableCell = (props) => {
548
595
  }, DeploymentTargets = (props) => {
549
596
  const { items, onDialogEdit } = props;
550
597
  return /* @__PURE__ */ jsx(Stack, { space: 5, children: items?.map((item) => /* @__PURE__ */ jsx(DeploymentTarget, { item, onDialogEdit }, item._id)) });
551
- }, formMachine = Machine(
552
- {
553
- context: {
554
- formData: {},
555
- message: ""
556
- },
557
- initial: "idle",
558
- states: {
559
- idle: {
560
- on: {
561
- CREATE: {
562
- actions: ["createDocument"],
563
- target: "creating"
564
- },
565
- DELETE: {
566
- actions: ["deleteDocument"],
567
- target: "deleting"
568
- },
569
- UPDATE: {
570
- actions: ["updateDocument"],
571
- target: "updating"
572
- }
573
- }
574
- },
575
- creating: {
576
- invoke: {
577
- src: "createDocumentService",
578
- onDone: { target: "success" },
579
- onError: { actions: ["setMessage"], target: "error" }
580
- },
581
- on: {
582
- RESOLVE: "success",
583
- REJECT: "error"
584
- }
585
- },
586
- updating: {
587
- invoke: {
588
- src: "updateDocumentService",
589
- onDone: { target: "success" },
590
- onError: { actions: ["setMessage"], target: "error" }
598
+ }, formMachine = setup({
599
+ types: {},
600
+ actions: {
601
+ setId: assign({
602
+ id: ({ event }) => (assertEvent(event, ["UPDATE", "DELETE"]), event.id)
603
+ }),
604
+ setFormData: assign({
605
+ formData: ({ event }) => (assertEvent(event, ["CREATE", "UPDATE"]), event.formData)
606
+ }),
607
+ setMessage: assign({
608
+ message: ({ event }) => "data" in event && event.data && typeof event.data == "object" && "details" in event.data && event.data.details && typeof event.data.details == "object" && "description" in event.data.details ? event.data.details.description : "An error occurred"
609
+ }),
610
+ setDocument: assign({
611
+ document: ({ event }) => event.output
612
+ })
613
+ },
614
+ actors: {
615
+ "create document": fromPromise(
616
+ ({ input }) => input.client.create({
617
+ _id: `vercel.${uuid()}`,
618
+ _type: DEPLOYMENT_TARGET_DOCUMENT_TYPE,
619
+ ...input.formData
620
+ })
621
+ ),
622
+ "update document": fromPromise(
623
+ ({ input }) => input.client.patch(input.id).set(input.formData).commit()
624
+ ),
625
+ "delete document": fromPromise(({ input }) => input.client.delete(input.id))
626
+ }
627
+ }).createMachine({
628
+ /** @xstate-layout N4IgpgJg5mDOIC5QAoC2BDAxgCwJYDswBKAOlwgBswBiAYQCUBRAQQBVGBtABgF1FQADgHtYuAC64h+fiAAeiAIwBmAGwkuGjQFYALAE4AHACYdWgwYA0IAJ6IjKgOwkdXFUYVa9h-Ua5KAvv5WaFh4hKTkVNQAqgAKACJsnLwywqISUjLyCMpqmtr6xqbmVrYIBgokWvlGWkpaCgZeKoHBGDgExGSUNPGMADKM7Nx8SCBp4pLSY9m56vm6hiZmljaIOipqdXpcDk1aWiYqBlqtICEd4SSYAE5g6BL4UNQQUmBk+ABuQgDW77f3MRgeJCTAAV1QYHwYmYmDEQhuI1SIkmmRmiGOShIDiUOh0SiaCgUegcDj0pTsjhI5iMewUpPsTSMZwuYS6AIeBGeYBuNwRJAEFAeADMEahrncHsDQRCoTC4QikWMJhlpqBspjsbj8YTiaTyWsEKouNT6noiX5zUpiQEgud2mzSGCBBBOU8Xm8Pt8-iRna6gSDwZDobD4YiUsqUaqshiDFicXiCea9WSKeVKiSVIclEYlIY-BUWQ7Ok6XW7ubz+YKRWLfWWAzLg-Kw0rBFGpjGEJqEzrkyTU4b6ToSHojHos7VXEc6kXQiWSBAwFRHs9XoQvb93ovl9Kg3LQ4qI230h30V241rE7r+wayro1A4dO4VHotA5fPTTnbWfPt2AV9QPJ8jcApCmIoo3OKf4NnuIYKuGozHqiapyLG8bakmRI3mmpjxk0XAuEoXAHI+DgtGc+BCIu8BjD+4TIieaLqogAC0Khpmxs6XF0kRgAxyGdk+aYKLSVR7Fweg6A4IkGFwChcY6EqAly-HRmeY7DnSY5GHGL4qFwRhpjpJpmriDjVMRLgGAp84ckCECqaezEIHoObUuZuwKH4xGPgoRnmCQpmOAcqhmPJ37Flcfrlo5TGoQgY4mgYHkeAS+iqH5hqSc4dSuCo+I6SoSjvjZUX1pAsUodkrlGO51TSd5b46JlZRebVuG7IcjRmA05FtHOVzQSpkaMVVdivs4CibHGxg6biSg4ZsJD2AccaFEVGwOKVXTQRVI0CWeNV1Z5jW+WmujDj4HjmMRnhEttpBAQilWdkdyX1V5RFNS1iAEpU1pHER9JWjogSBEAA */
629
+ context: ({ input }) => ({
630
+ client: input.client,
631
+ formData: {},
632
+ message: ""
633
+ }),
634
+ initial: "idle",
635
+ states: {
636
+ idle: {
637
+ on: {
638
+ CREATE: {
639
+ actions: ["setFormData"],
640
+ target: "creating"
591
641
  },
592
- on: {
593
- RESOLVE: "success",
594
- REJECT: "error"
595
- }
596
- },
597
- deleting: {
598
- invoke: {
599
- src: "deleteDocumentService",
600
- onDone: { target: "success" },
601
- onError: { actions: ["setMessage"], target: "error" }
642
+ UPDATE: {
643
+ actions: ["setId", "setFormData"],
644
+ target: "updating"
602
645
  },
603
- on: {
604
- RESOLVE: "success",
605
- REJECT: "error"
606
- }
607
- },
608
- success: {
609
- invoke: {
610
- src: "formSubmittedService"
646
+ DELETE: {
647
+ actions: "setId",
648
+ target: "deleting"
611
649
  }
612
- },
613
- error: {}
614
- }
615
- },
616
- {
617
- actions: {
618
- setMessage: assign((_context, event) => ({
619
- message: event.data.details.description
620
- })),
621
- createDocument: assign((_context, event) => ({
622
- formData: event.formData
623
- })),
624
- deleteDocument: assign(() => ({
625
- // id: event.id,
626
- })),
627
- updateDocument: assign((_context, event) => ({
628
- formData: event.formData
629
- }))
630
- }
650
+ }
651
+ },
652
+ creating: {
653
+ tags: ["busy"],
654
+ invoke: {
655
+ src: "create document",
656
+ id: "createDocumentActor",
657
+ input: ({ context }) => ({ client: context.client, formData: context.formData }),
658
+ onDone: { actions: "setDocument", target: "created" },
659
+ onError: { actions: "setMessage", target: "error" }
660
+ }
661
+ },
662
+ created: { type: "final" },
663
+ updating: {
664
+ tags: ["busy"],
665
+ invoke: {
666
+ src: "update document",
667
+ id: "updateDocumentActor",
668
+ input: ({ context }) => ({
669
+ client: context.client,
670
+ id: context.id,
671
+ formData: context.formData
672
+ }),
673
+ onDone: { actions: "setDocument", target: "updated" },
674
+ onError: { actions: "setMessage", target: "error" }
675
+ }
676
+ },
677
+ updated: { type: "final" },
678
+ deleting: {
679
+ tags: ["busy"],
680
+ invoke: {
681
+ src: "delete document",
682
+ id: "deleteDocumentActor",
683
+ input: ({ context }) => ({ client: context.client, id: context.id }),
684
+ onDone: { target: "deleted" },
685
+ onError: { actions: "setMessage", target: "error" }
686
+ }
687
+ },
688
+ deleted: { type: "final" },
689
+ error: { type: "final" }
631
690
  }
632
- ), sanitizeFormData = (formData) => Object.keys(formData).reduce((acc, key) => {
691
+ }), sanitizeFormData = (formData) => Object.keys(formData).reduce((acc, key) => {
633
692
  const val = formData[key];
634
693
  return typeof val == "object" && val !== null && val.constructor !== Array ? acc[key] = sanitizeFormData(val) : val === "" || typeof val > "u" || val?.length === 0 ? acc[key] = null : typeof val == "string" && val ? acc[key] = formData[key].trim() : acc[key] = formData[key], acc;
635
694
  }, {}), StyledErrorOutlineIcon = styled(ErrorOutlineIcon)(({ theme }) => ({
@@ -687,47 +746,9 @@ const formSchema = yup.object().shape({
687
746
  teamId: yup.string(),
688
747
  token: yup.string().required("Vercel Account Token cannot be empty")
689
748
  }), DialogForm = (props) => {
690
- const { deploymentTarget, onClose, onCreate, onDelete, onUpdate } = props, client = useSanityClient(), [formState, formStateTransition] = useMachine(formMachine, {
691
- services: {
692
- formSubmittedService: async () => {
693
- onClose();
694
- },
695
- // TODO: refactor
696
- createDocumentService: async (_context, event) => {
697
- let document;
698
- try {
699
- return document = await client.create({
700
- _id: `vercel.${uuid()}`,
701
- _type: DEPLOYMENT_TARGET_DOCUMENT_TYPE,
702
- ...event.formData
703
- }), onCreate && onCreate(document), Promise.resolve();
704
- } catch (e) {
705
- return Promise.reject(e);
706
- }
707
- },
708
- // TODO: refactor
709
- deleteDocumentService: async () => {
710
- if (deploymentTarget)
711
- try {
712
- return await client.delete(deploymentTarget._id), onDelete && onDelete(deploymentTarget._id), Promise.resolve();
713
- } catch (e) {
714
- return Promise.reject(e);
715
- }
716
- return Promise.resolve();
717
- },
718
- // TODO: refactor
719
- updateDocumentService: async (_context, event) => {
720
- let document;
721
- if (deploymentTarget)
722
- try {
723
- return document = await client.patch(deploymentTarget._id).set(event.formData).commit(), onUpdate && onUpdate(document), Promise.resolve();
724
- } catch (e) {
725
- return Promise.reject(e);
726
- }
727
- return Promise.resolve();
728
- }
729
- }
730
- }), formUpdating = formState.matches("creating") || formState.matches("deleting") || formState.matches("updating"), {
749
+ const { deploymentTarget, onClose, onCreate, onDelete, onUpdate } = props, client = useSanityClient(), toast = useToast(), [formState, formStateTransition, formStateActorRef] = useActor(formMachine, {
750
+ input: { client }
751
+ }), formUpdating = formState.hasTag("busy"), {
731
752
  formState: { errors, isDirty, isValid },
732
753
  handleSubmit,
733
754
  register
@@ -743,21 +764,30 @@ const formSchema = yup.object().shape({
743
764
  },
744
765
  mode: "onChange",
745
766
  resolver: yupResolver(formSchema)
746
- }), onSubmit = async (formData) => {
767
+ });
768
+ useEffect(() => {
769
+ formState.matches("error") && toast.push({
770
+ status: "error",
771
+ title: formState.context.message || "An error occurred"
772
+ }), formState.status === "done" && onClose();
773
+ }, [formState, onClose, toast]);
774
+ const onSubmit = async (formData) => {
747
775
  const sanitizedFormData = sanitizeFormData(formData);
748
- await formStateTransition(deploymentTarget ? "UPDATE" : "CREATE", {
749
- formData: sanitizedFormData
750
- });
751
- }, handleDelete = () => {
752
- formStateTransition("DELETE", { id: deploymentTarget?._id });
776
+ formStateTransition(deploymentTarget ? { type: "UPDATE", id: deploymentTarget._id, formData: sanitizedFormData } : { type: "CREATE", formData: sanitizedFormData }), await toPromise(formStateActorRef);
777
+ const snapshot = formStateActorRef.getSnapshot(), { document } = snapshot.context;
778
+ document && (snapshot.matches("created") ? onCreate?.(document) : snapshot.matches("updated") && onUpdate?.(document));
779
+ }, handleDelete = async () => {
780
+ const id = deploymentTarget._id;
781
+ formStateTransition({ type: "DELETE", id }), await toPromise(formStateActorRef), formStateActorRef.getSnapshot().matches("deleted") && onDelete?.(id);
753
782
  };
754
783
  return /* @__PURE__ */ jsx(
755
784
  Dialog,
756
785
  {
757
- footer: /* @__PURE__ */ jsx(() => /* @__PURE__ */ jsx(Box, { padding: 3, children: /* @__PURE__ */ jsxs(Flex, { justify: deploymentTarget ? "space-between" : "flex-end", children: [
786
+ footer: /* @__PURE__ */ jsx(Box, { padding: 3, children: /* @__PURE__ */ jsxs(Flex, { justify: deploymentTarget ? "space-between" : "flex-end", children: [
758
787
  deploymentTarget && /* @__PURE__ */ jsx(
759
788
  Button,
760
789
  {
790
+ loading: formState.matches("deleting"),
761
791
  disabled: formUpdating,
762
792
  fontSize: 1,
763
793
  mode: "bleed",
@@ -769,14 +799,15 @@ const formSchema = yup.object().shape({
769
799
  /* @__PURE__ */ jsx(
770
800
  Button,
771
801
  {
772
- disabled: formUpdating || !isDirty || !isValid,
802
+ loading: formState.matches("creating") || formState.matches("updating"),
803
+ disabled: !isDirty || !isValid,
773
804
  fontSize: 1,
774
805
  onClick: handleSubmit(onSubmit),
775
806
  text: deploymentTarget ? "Update and close" : "Create",
776
807
  tone: "primary"
777
808
  }
778
809
  )
779
- ] }) }), {}),
810
+ ] }) }),
780
811
  header: `${deploymentTarget ? "Edit" : "Create"} deployment target`,
781
812
  id: "create",
782
813
  onClose,
@@ -846,72 +877,76 @@ const formSchema = yup.object().shape({
846
877
  ] })
847
878
  }
848
879
  );
849
- }, dialogMachine = () => Machine(
850
- {
851
- context: {
852
- editDeploymentTarget: void 0
853
- },
854
- initial: "idle",
855
- states: {
856
- idle: {
857
- entry: assign({
858
- editDeploymentTarget: () => {
859
- }
860
- }),
861
- on: {
862
- CREATE: "create",
863
- EDIT: {
864
- actions: ["setEditDeploymentTarget"],
865
- target: "edit"
866
- }
880
+ }, dialogMachine = setup({
881
+ types: {
882
+ context: {},
883
+ events: {}
884
+ },
885
+ actions: {
886
+ setEditDeploymentTarget: assign({
887
+ editDeploymentTarget: ({ event }) => (assertEvent(event, "EDIT"), event.deploymentTarget)
888
+ })
889
+ }
890
+ }).createMachine({
891
+ /** @xstate-layout N4IgpgJg5mDOIC5QAoC2BDAxgCwJYDswBKAOlwgBswBiAYQCUBRAQQBVGBtABgF1FQADgHtYuAC64h+fiAAeiAEwKArCQCcANgAcAdmUbNOhVx0BGLQBoQAT0SmAzApJcXXexoAsW5fbWaFAL4BVmhYeISk5FTUjAAiAJKs3HxIIMKiElIy8ghKqpq6+obGZpY2ivb2zq4e5moeXKZc3kEhGDgExCSQ4nQAMgDyAMqcvDLp4pLSqTn2DSQefn7uyq5aWvZWtgjmTqsuvnU6XMoK9q0goR0RJJgATmDoYjS0gyPJ4yKTWTOIc1wLJZqFZrDZbRBaUwkfZuew6SFcepuILBED4IQQOAyK7hYifDJTbKIAC0GnBCFJFxxnUilDA+O+01AOQ8CnJGxIGn29lMpjUxhcCh0VPauNIPTEDMyTLkiA8PhIxh5Cg8DS8pgM5L5UOalSMah0cP05hFYRptweT3pqQm0qJCHlVSVphVashmvKCDUAN17j0XNMqrUyhRASAA */
892
+ context: {
893
+ editDeploymentTarget: void 0
894
+ },
895
+ initial: "idle",
896
+ states: {
897
+ idle: {
898
+ entry: assign({
899
+ editDeploymentTarget: () => {
867
900
  }
868
- },
869
- edit: {
870
- on: {
871
- CLOSE: "idle"
901
+ }),
902
+ on: {
903
+ CREATE: {
904
+ target: "create"
905
+ },
906
+ EDIT: {
907
+ actions: "setEditDeploymentTarget",
908
+ target: "edit"
872
909
  }
873
- },
874
- create: {
875
- on: {
876
- CLOSE: "idle"
910
+ }
911
+ },
912
+ edit: {
913
+ on: {
914
+ CLOSE: {
915
+ target: "idle"
916
+ }
917
+ }
918
+ },
919
+ create: {
920
+ on: {
921
+ CLOSE: {
922
+ target: "idle"
877
923
  }
878
924
  }
879
925
  }
880
- },
881
- {
882
- actions: {
883
- setEditDeploymentTarget: assign((_context, event) => ({
884
- editDeploymentTarget: event.deploymentTarget
885
- }))
926
+ }
927
+ }), queryClient = new QueryClient({
928
+ defaultOptions: {
929
+ queries: {
930
+ gcTime: 0,
931
+ staleTime: 0
886
932
  }
887
933
  }
888
- ), Widget = () => {
934
+ }), Widget = () => {
889
935
  const client = useSanityClient(), [deploymentTargetListState, deploymentTargetListStateTransition] = useMachine(
890
936
  deploymentTargetListMachine,
891
- {
892
- services: {
893
- fetchDataService: () => client.fetch(`*[_type == "${DEPLOYMENT_TARGET_DOCUMENT_TYPE}"] | order(name asc)`).then((result) => result)
894
- }
895
- }
896
- ), [dialogState, dialogStateTransition] = useMachine(dialogMachine), queryClient = new QueryClient({
897
- defaultOptions: {
898
- queries: {
899
- gcTime: 0,
900
- staleTime: 0
901
- }
902
- }
903
- }), handleDialogClose = () => {
904
- dialogStateTransition("CLOSE");
937
+ { input: { client } }
938
+ ), [dialogState, dialogStateTransition] = useMachine(dialogMachine), handleDialogClose = () => {
939
+ dialogStateTransition({ type: "CLOSE" });
905
940
  }, handleDialogShowCreate = () => {
906
- dialogStateTransition("CREATE");
941
+ dialogStateTransition({ type: "CREATE" });
907
942
  }, handleDialogShowEdit = (deploymentTarget) => {
908
- dialogStateTransition("EDIT", { deploymentTarget });
943
+ dialogStateTransition({ type: "EDIT", deploymentTarget });
909
944
  }, handleTargetCreate = (deploymentTarget) => {
910
- deploymentTargetListStateTransition("CREATE", { deploymentTarget });
945
+ deploymentTargetListStateTransition({ type: "CREATE", deploymentTarget });
911
946
  }, handleTargetDelete = (id) => {
912
- deploymentTargetListStateTransition("DELETE", { id });
947
+ deploymentTargetListStateTransition({ type: "DELETE", id });
913
948
  }, handleTargetUpdate = (deploymentTarget) => {
914
- deploymentTargetListStateTransition("UPDATE", { deploymentTarget });
949
+ deploymentTargetListStateTransition({ type: "UPDATE", deploymentTarget });
915
950
  };
916
951
  return /* @__PURE__ */ jsx(ToastProvider, { zOffset: Z_INDEX_TOAST_PROVIDER, children: /* @__PURE__ */ jsxs(QueryClientProvider, { client: queryClient, children: [
917
952
  /* @__PURE__ */ jsxs(Card, { radius: 2, style: { overflow: "hidden " }, children: [
@@ -929,12 +964,12 @@ const formSchema = yup.object().shape({
929
964
  ] }),
930
965
  /* @__PURE__ */ jsxs(Box, { children: [
931
966
  deploymentTargetListState.matches("pending") && /* @__PURE__ */ jsx(Box, { paddingX: 3, paddingY: 4, children: /* @__PURE__ */ jsx(Text, { children: "Loading..." }) }),
932
- deploymentTargetListState.matches("ready.withoutData") && /* @__PURE__ */ jsx(Box, { paddingX: 3, paddingY: 4, children: /* @__PURE__ */ jsxs(Text, { children: [
967
+ deploymentTargetListState.matches({ ready: "withoutData" }) && /* @__PURE__ */ jsx(Box, { paddingX: 3, paddingY: 4, children: /* @__PURE__ */ jsxs(Text, { children: [
933
968
  "No deployment targets found.",
934
969
  " ",
935
970
  /* @__PURE__ */ jsx("a", { onClick: handleDialogShowCreate, style: { cursor: "pointer" }, children: "Create a new target?" })
936
971
  ] }) }),
937
- deploymentTargetListState.matches("ready.withData") && /* @__PURE__ */ jsx(
972
+ deploymentTargetListState.matches({ ready: "withData" }) && /* @__PURE__ */ jsx(
938
973
  DeploymentTargets,
939
974
  {
940
975
  items: deploymentTargetListState.context.results,