sanity-plugin-dashboard-widget-vercel 3.1.1 → 3.1.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/lib/index.js +377 -345
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +378 -347
- package/lib/index.mjs.map +1 -1
- package/package.json +19 -20
- package/src/app.tsx +22 -30
- package/src/components/DeployButton/index.tsx +8 -7
- package/src/components/DialogForm/index.tsx +96 -116
- package/src/components/FormFieldInputLabel/index.tsx +0 -1
- package/src/components/FormFieldInputText/index.tsx +6 -5
- package/src/machines/deploy.ts +94 -91
- package/src/machines/deploymentTargetList.ts +113 -90
- package/src/machines/dialog.ts +44 -44
- package/src/machines/form.ts +136 -91
- package/src/machines/refresh.ts +22 -18
- package/src/utils/fetcher.ts +0 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {UploadIcon} from '@sanity/icons'
|
|
2
2
|
import {Box, Button, useToast} from '@sanity/ui'
|
|
3
3
|
import {useMachine} from '@xstate/react'
|
|
4
|
-
import React, {useEffect
|
|
4
|
+
import React, {useEffect} from 'react'
|
|
5
5
|
|
|
6
6
|
import {WIDGET_NAME} from '../../constants'
|
|
7
|
-
import deployMachine from '../../machines/deploy'
|
|
7
|
+
import {deployMachine} from '../../machines/deploy'
|
|
8
8
|
import StateDebug from '../StateDebug'
|
|
9
9
|
|
|
10
10
|
type Props = {
|
|
@@ -16,9 +16,9 @@ type Props = {
|
|
|
16
16
|
const DeployButton = (props: Props) => {
|
|
17
17
|
const {deployHook, onDeploySuccess, targetName} = props
|
|
18
18
|
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
const [deployState, deployStateTransition, deployStateInterpreter] = useMachine(deployMachine, {
|
|
20
|
+
input: {deployHook},
|
|
21
|
+
})
|
|
22
22
|
|
|
23
23
|
const toast = useToast()
|
|
24
24
|
|
|
@@ -54,18 +54,19 @@ const DeployButton = (props: Props) => {
|
|
|
54
54
|
}, [isError, isSuccess, toast, targetName, deployState.context.error])
|
|
55
55
|
|
|
56
56
|
useEffect(() => {
|
|
57
|
-
deployStateInterpreter.
|
|
57
|
+
const subscription = deployStateInterpreter.subscribe((state) => {
|
|
58
58
|
if (state.value === 'success') {
|
|
59
59
|
if (onDeploySuccess) {
|
|
60
60
|
onDeploySuccess()
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
})
|
|
64
|
+
|
|
65
|
+
return () => subscription.unsubscribe()
|
|
64
66
|
}, [deployStateInterpreter, onDeploySuccess])
|
|
65
67
|
|
|
66
68
|
return (
|
|
67
69
|
<Box padding={3} style={{position: 'relative'}}>
|
|
68
|
-
{/* xstate debug */}
|
|
69
70
|
<StateDebug name="Deploy" state={deployState} />
|
|
70
71
|
|
|
71
72
|
<Button
|
|
@@ -1,19 +1,17 @@
|
|
|
1
|
-
// @ts-expect-error - fix typings later
|
|
2
1
|
import {yupResolver} from '@hookform/resolvers/yup'
|
|
3
|
-
import {Box, Button, Dialog, Flex, Stack} from '@sanity/ui'
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import React, {FC} from 'react'
|
|
7
|
-
// @ts-expect-error - fix typings later
|
|
2
|
+
import {Box, Button, Dialog, Flex, Stack, useToast} from '@sanity/ui'
|
|
3
|
+
import {useActor} from '@xstate/react'
|
|
4
|
+
import React, {FC, useEffect} from 'react'
|
|
8
5
|
import {useForm} from 'react-hook-form'
|
|
9
6
|
import * as yup from 'yup'
|
|
10
7
|
|
|
11
|
-
import {
|
|
12
|
-
import formMachine from '../../machines/form'
|
|
8
|
+
import {Z_INDEX_DIALOG} from '../../constants'
|
|
9
|
+
import {formMachine} from '../../machines/form'
|
|
13
10
|
import sanitizeFormData from '../../utils/sanitizeFormData'
|
|
14
11
|
import FormFieldInputText from '../FormFieldInputText'
|
|
15
12
|
import {Sanity} from '../../types'
|
|
16
13
|
import {useSanityClient} from '../../client'
|
|
14
|
+
import {toPromise} from 'xstate'
|
|
17
15
|
|
|
18
16
|
type Props = {
|
|
19
17
|
deploymentTarget?: Sanity.DeploymentTarget
|
|
@@ -44,129 +42,111 @@ const formSchema = yup.object().shape({
|
|
|
44
42
|
const DialogForm: FC<Props> = (props: Props) => {
|
|
45
43
|
const {deploymentTarget, onClose, onCreate, onDelete, onUpdate} = props
|
|
46
44
|
const client = useSanityClient()
|
|
45
|
+
const toast = useToast()
|
|
47
46
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
services: {
|
|
51
|
-
formSubmittedService: async () => {
|
|
52
|
-
onClose()
|
|
53
|
-
},
|
|
54
|
-
// TODO: refactor
|
|
55
|
-
createDocumentService: async (_context, event: any) => {
|
|
56
|
-
let document
|
|
57
|
-
try {
|
|
58
|
-
document = await client.create({
|
|
59
|
-
_id: `vercel.${uuid()}`,
|
|
60
|
-
_type: DEPLOYMENT_TARGET_DOCUMENT_TYPE,
|
|
61
|
-
...event.formData,
|
|
62
|
-
})
|
|
63
|
-
if (onCreate) {
|
|
64
|
-
onCreate(document as Sanity.DeploymentTarget)
|
|
65
|
-
}
|
|
66
|
-
return Promise.resolve()
|
|
67
|
-
} catch (e) {
|
|
68
|
-
return Promise.reject(e)
|
|
69
|
-
}
|
|
70
|
-
},
|
|
71
|
-
// TODO: refactor
|
|
72
|
-
deleteDocumentService: async () => {
|
|
73
|
-
if (deploymentTarget) {
|
|
74
|
-
try {
|
|
75
|
-
await client.delete(deploymentTarget._id)
|
|
76
|
-
if (onDelete) {
|
|
77
|
-
onDelete(deploymentTarget._id)
|
|
78
|
-
}
|
|
79
|
-
return Promise.resolve()
|
|
80
|
-
} catch (e) {
|
|
81
|
-
return Promise.reject(e)
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
return Promise.resolve()
|
|
85
|
-
},
|
|
86
|
-
// TODO: refactor
|
|
87
|
-
updateDocumentService: async (_context, event: any) => {
|
|
88
|
-
let document
|
|
89
|
-
if (deploymentTarget) {
|
|
90
|
-
try {
|
|
91
|
-
document = await client.patch(deploymentTarget._id).set(event.formData).commit()
|
|
92
|
-
if (onUpdate) {
|
|
93
|
-
onUpdate(document as Sanity.DeploymentTarget)
|
|
94
|
-
}
|
|
95
|
-
return Promise.resolve()
|
|
96
|
-
} catch (e) {
|
|
97
|
-
return Promise.reject(e)
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
return Promise.resolve()
|
|
101
|
-
},
|
|
102
|
-
},
|
|
47
|
+
const [formState, formStateTransition, formStateActorRef] = useActor(formMachine, {
|
|
48
|
+
input: {client},
|
|
103
49
|
})
|
|
104
50
|
|
|
105
|
-
const formUpdating =
|
|
106
|
-
formState.matches('creating') || formState.matches('deleting') || formState.matches('updating')
|
|
51
|
+
const formUpdating = formState.hasTag('busy')
|
|
107
52
|
|
|
108
|
-
// react-hook-form
|
|
53
|
+
// react-hook-form v7
|
|
109
54
|
const {
|
|
110
|
-
// Read the formState before render to subscribe the form state through Proxy
|
|
111
55
|
formState: {errors, isDirty, isValid},
|
|
112
56
|
handleSubmit,
|
|
113
57
|
register,
|
|
114
|
-
} = useForm({
|
|
58
|
+
} = useForm<FormData>({
|
|
59
|
+
// @ts-expect-error - fix typings later
|
|
115
60
|
defaultValues: {
|
|
116
61
|
deployHook: deploymentTarget?.deployHook || '',
|
|
117
62
|
deployLimit: deploymentTarget?.deployLimit || 5,
|
|
118
|
-
name: deploymentTarget?.name,
|
|
119
|
-
projectId: deploymentTarget?.projectId,
|
|
63
|
+
name: deploymentTarget?.name || '',
|
|
64
|
+
projectId: deploymentTarget?.projectId || '',
|
|
120
65
|
teamId: deploymentTarget?.teamId || '',
|
|
121
|
-
token: deploymentTarget?.token,
|
|
66
|
+
token: deploymentTarget?.token || '',
|
|
122
67
|
},
|
|
123
68
|
mode: 'onChange',
|
|
124
69
|
resolver: yupResolver(formSchema),
|
|
125
70
|
})
|
|
126
71
|
|
|
72
|
+
/**
|
|
73
|
+
* Handle errors and reaching the done state
|
|
74
|
+
*/
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
if (formState.matches('error')) {
|
|
77
|
+
toast.push({
|
|
78
|
+
status: 'error',
|
|
79
|
+
title: formState.context.message || 'An error occurred',
|
|
80
|
+
})
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* If the machine is done it means it reached updated, created, deleted or error state.
|
|
84
|
+
* We don't care which one, we just want to close the dialog
|
|
85
|
+
*/
|
|
86
|
+
if (formState.status === 'done') {
|
|
87
|
+
onClose()
|
|
88
|
+
}
|
|
89
|
+
}, [formState, onClose, toast])
|
|
90
|
+
|
|
127
91
|
// Callbacks
|
|
128
92
|
// - submit react-hook-form
|
|
129
93
|
const onSubmit = async (formData: FormData) => {
|
|
130
94
|
const sanitizedFormData = sanitizeFormData(formData)
|
|
131
|
-
|
|
132
|
-
formData: sanitizedFormData
|
|
133
|
-
}
|
|
95
|
+
if (deploymentTarget) {
|
|
96
|
+
formStateTransition({type: 'UPDATE', id: deploymentTarget._id, formData: sanitizedFormData})
|
|
97
|
+
} else {
|
|
98
|
+
formStateTransition({type: 'CREATE', formData: sanitizedFormData})
|
|
99
|
+
}
|
|
100
|
+
await toPromise(formStateActorRef)
|
|
101
|
+
const snapshot = formStateActorRef.getSnapshot()
|
|
102
|
+
const {document} = snapshot.context
|
|
103
|
+
if (!document) return
|
|
104
|
+
if (snapshot.matches('created')) {
|
|
105
|
+
onCreate?.(document)
|
|
106
|
+
} else if (snapshot.matches('updated')) {
|
|
107
|
+
onUpdate?.(document)
|
|
108
|
+
}
|
|
134
109
|
}
|
|
135
110
|
|
|
136
|
-
const handleDelete = () => {
|
|
137
|
-
|
|
111
|
+
const handleDelete = async () => {
|
|
112
|
+
const id = deploymentTarget!._id
|
|
113
|
+
formStateTransition({type: 'DELETE', id})
|
|
114
|
+
await toPromise(formStateActorRef)
|
|
115
|
+
if (formStateActorRef.getSnapshot().matches('deleted')) {
|
|
116
|
+
onDelete?.(id)
|
|
117
|
+
}
|
|
138
118
|
}
|
|
139
119
|
|
|
140
|
-
const Footer = () => (
|
|
141
|
-
<Box padding={3}>
|
|
142
|
-
<Flex justify={deploymentTarget ? 'space-between' : 'flex-end'}>
|
|
143
|
-
{/* Delete button */}
|
|
144
|
-
{deploymentTarget && (
|
|
145
|
-
<Button
|
|
146
|
-
disabled={formUpdating}
|
|
147
|
-
fontSize={1}
|
|
148
|
-
mode="bleed"
|
|
149
|
-
onClick={handleDelete}
|
|
150
|
-
text="Delete"
|
|
151
|
-
tone="critical"
|
|
152
|
-
/>
|
|
153
|
-
)}
|
|
154
|
-
|
|
155
|
-
{/* Submit button */}
|
|
156
|
-
<Button
|
|
157
|
-
disabled={formUpdating || !isDirty || !isValid}
|
|
158
|
-
fontSize={1}
|
|
159
|
-
onClick={handleSubmit(onSubmit)}
|
|
160
|
-
text={deploymentTarget ? 'Update and close' : 'Create'}
|
|
161
|
-
tone="primary"
|
|
162
|
-
/>
|
|
163
|
-
</Flex>
|
|
164
|
-
</Box>
|
|
165
|
-
)
|
|
166
|
-
|
|
167
120
|
return (
|
|
168
121
|
<Dialog
|
|
169
|
-
footer={
|
|
122
|
+
footer={
|
|
123
|
+
<Box padding={3}>
|
|
124
|
+
<Flex justify={deploymentTarget ? 'space-between' : 'flex-end'}>
|
|
125
|
+
{/* Delete button */}
|
|
126
|
+
{deploymentTarget && (
|
|
127
|
+
<Button
|
|
128
|
+
loading={formState.matches('deleting')}
|
|
129
|
+
disabled={formUpdating}
|
|
130
|
+
fontSize={1}
|
|
131
|
+
mode="bleed"
|
|
132
|
+
onClick={handleDelete}
|
|
133
|
+
text="Delete"
|
|
134
|
+
tone="critical"
|
|
135
|
+
/>
|
|
136
|
+
)}
|
|
137
|
+
|
|
138
|
+
{/* Submit button */}
|
|
139
|
+
<Button
|
|
140
|
+
loading={formState.matches('creating') || formState.matches('updating')}
|
|
141
|
+
disabled={!isDirty || !isValid}
|
|
142
|
+
fontSize={1}
|
|
143
|
+
onClick={handleSubmit(onSubmit)}
|
|
144
|
+
text={deploymentTarget ? 'Update and close' : 'Create'}
|
|
145
|
+
tone="primary"
|
|
146
|
+
/>
|
|
147
|
+
</Flex>
|
|
148
|
+
</Box>
|
|
149
|
+
}
|
|
170
150
|
header={`${deploymentTarget ? 'Edit' : 'Create'} deployment target`}
|
|
171
151
|
id="create"
|
|
172
152
|
onClose={onClose}
|
|
@@ -186,24 +166,24 @@ const DialogForm: FC<Props> = (props: Props) => {
|
|
|
186
166
|
description="Name displayed in this plugin (e.g. production, staging)"
|
|
187
167
|
error={errors?.name}
|
|
188
168
|
label="Name"
|
|
189
|
-
|
|
190
|
-
|
|
169
|
+
// @ts-expect-error - fix typings later
|
|
170
|
+
{...register('name')}
|
|
191
171
|
/>
|
|
192
172
|
|
|
193
173
|
<FormFieldInputText
|
|
194
174
|
disabled={formUpdating}
|
|
195
175
|
error={errors?.token}
|
|
196
176
|
label="Vercel Account Token"
|
|
197
|
-
|
|
198
|
-
|
|
177
|
+
// @ts-expect-error - fix typings later
|
|
178
|
+
{...register('token')}
|
|
199
179
|
/>
|
|
200
180
|
|
|
201
181
|
<FormFieldInputText
|
|
202
182
|
disabled={formUpdating}
|
|
203
183
|
error={errors?.projectId}
|
|
204
184
|
label="Vercel Project ID"
|
|
205
|
-
|
|
206
|
-
|
|
185
|
+
// @ts-expect-error - fix typings later
|
|
186
|
+
{...register('projectId')}
|
|
207
187
|
/>
|
|
208
188
|
|
|
209
189
|
<FormFieldInputText
|
|
@@ -211,8 +191,8 @@ const DialogForm: FC<Props> = (props: Props) => {
|
|
|
211
191
|
disabled={formUpdating}
|
|
212
192
|
error={errors?.teamId}
|
|
213
193
|
label="Vercel Team ID (optional)"
|
|
214
|
-
|
|
215
|
-
|
|
194
|
+
// @ts-expect-error - fix typings later
|
|
195
|
+
{...register('teamId')}
|
|
216
196
|
/>
|
|
217
197
|
|
|
218
198
|
<FormFieldInputText
|
|
@@ -220,16 +200,16 @@ const DialogForm: FC<Props> = (props: Props) => {
|
|
|
220
200
|
disabled={formUpdating}
|
|
221
201
|
error={errors?.deployHook}
|
|
222
202
|
label="Vercel Deploy Hook (optional)"
|
|
223
|
-
|
|
224
|
-
|
|
203
|
+
// @ts-expect-error - fix typings later
|
|
204
|
+
{...register('deployHook')}
|
|
225
205
|
/>
|
|
226
206
|
|
|
227
207
|
<FormFieldInputText
|
|
228
208
|
disabled={formUpdating}
|
|
229
209
|
error={errors?.deployLimit}
|
|
230
210
|
label="Number of deploys to display"
|
|
231
|
-
|
|
232
|
-
|
|
211
|
+
// @ts-expect-error - fix typings later
|
|
212
|
+
{...register('deployLimit', {valueAsNumber: true})}
|
|
233
213
|
/>
|
|
234
214
|
</Stack>
|
|
235
215
|
</Box>
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import {ErrorOutlineIcon} from '@sanity/icons'
|
|
2
2
|
import {Box, Inline, Text, Tooltip} from '@sanity/ui'
|
|
3
3
|
import React, {FC} from 'react'
|
|
4
|
-
// @ts-expect-error - fix typings later
|
|
5
4
|
import {FieldError} from 'react-hook-form'
|
|
6
5
|
import {styled} from 'styled-components'
|
|
7
6
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {Box, TextInput} from '@sanity/ui'
|
|
2
2
|
import React, {forwardRef} from 'react'
|
|
3
|
-
// @ts-expect-error - fix typings later
|
|
4
3
|
import {FieldError} from 'react-hook-form'
|
|
5
4
|
|
|
6
5
|
import FormFieldInputLabel from '../FormFieldInputLabel'
|
|
@@ -13,12 +12,12 @@ type Props = {
|
|
|
13
12
|
name: string
|
|
14
13
|
placeholder?: string
|
|
15
14
|
value?: string
|
|
15
|
+
onChange?: React.ChangeEventHandler<HTMLInputElement>
|
|
16
|
+
onBlur?: React.FocusEventHandler<HTMLInputElement>
|
|
16
17
|
}
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const FormFieldInputText = forwardRef<Ref, Props>((props: Props, ref) => {
|
|
21
|
-
const {description, disabled, error, label, name, placeholder, value} = props
|
|
19
|
+
const FormFieldInputText = forwardRef<HTMLInputElement, Props>((props: Props, ref) => {
|
|
20
|
+
const {description, disabled, error, label, name, placeholder, value, onChange, onBlur} = props
|
|
22
21
|
|
|
23
22
|
return (
|
|
24
23
|
<Box>
|
|
@@ -33,6 +32,8 @@ const FormFieldInputText = forwardRef<Ref, Props>((props: Props, ref) => {
|
|
|
33
32
|
id={name}
|
|
34
33
|
name={name}
|
|
35
34
|
placeholder={placeholder}
|
|
35
|
+
onChange={onChange}
|
|
36
|
+
onBlur={onBlur}
|
|
36
37
|
ref={ref}
|
|
37
38
|
/>
|
|
38
39
|
</Box>
|
package/src/machines/deploy.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {assign, Machine} from 'xstate'
|
|
1
|
+
import {assign, setup, fromPromise} from 'xstate'
|
|
3
2
|
import {Vercel} from '../types'
|
|
4
3
|
|
|
5
4
|
type Context = {
|
|
5
|
+
deployHook: string
|
|
6
6
|
disabled: boolean
|
|
7
7
|
feedback?: string
|
|
8
8
|
label?: string
|
|
@@ -11,104 +11,107 @@ type Context = {
|
|
|
11
11
|
|
|
12
12
|
type Event = {type: 'DEPLOY'}
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
idle: {}
|
|
17
|
-
deploying: {}
|
|
18
|
-
success: {}
|
|
19
|
-
error: {}
|
|
20
|
-
}
|
|
14
|
+
interface DeployActorInput {
|
|
15
|
+
deployHook: string
|
|
21
16
|
}
|
|
22
17
|
|
|
23
|
-
const deployMachine = (
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
{
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
18
|
+
export const deployMachine = setup({
|
|
19
|
+
types: {
|
|
20
|
+
context: {} as Context,
|
|
21
|
+
events: {} as Event,
|
|
22
|
+
input: {} as DeployActorInput,
|
|
23
|
+
},
|
|
24
|
+
actors: {
|
|
25
|
+
deploy: fromPromise(async ({input, signal}: {input: DeployActorInput; signal: AbortSignal}) => {
|
|
26
|
+
try {
|
|
27
|
+
if (!input.deployHook) {
|
|
28
|
+
throw new Error('No deployHook URL defined')
|
|
29
|
+
}
|
|
30
|
+
const res = await fetch(input.deployHook, {method: 'POST', signal})
|
|
31
|
+
const data = await res.json()
|
|
32
|
+
if (!res.ok) {
|
|
33
|
+
const errorMessage = (data?.error as Vercel.Error).message || res.statusText
|
|
34
|
+
throw errorMessage
|
|
35
|
+
}
|
|
36
|
+
} catch (err) {
|
|
37
|
+
if (typeof err === 'string') {
|
|
38
|
+
throw err
|
|
39
|
+
}
|
|
40
|
+
console.error('Unable to deploy with error:', err)
|
|
41
|
+
throw new Error('Please check the developer console for more information')
|
|
42
|
+
}
|
|
43
|
+
}),
|
|
44
|
+
},
|
|
45
|
+
}).createMachine({
|
|
46
|
+
/** @xstate-layout N4IgpgJg5mDOIC5QTABwDYHsCeA6AlhOmAMQAiAogAoAyA8gJoDaADALqKiqaz4Au+TADtOIAB6IATCxa4AnADYAHAHYArArUslAZjksNAGhDZEARk3yVmhSxVyHC-QBYAvq+MoMOXF6zZ8ISgSCGEwAiEAN0wAa3C-HwSAoIRA6IBjAEMBYVY2PNFuXhyRJHFENTMzXElFJSUzNTVnWx0FY1MESXVcZzUdM2k1OTUVBoV3TzR-X2mcQOCwACclzCXcDGyAMzWAW1nvPCSF1KjMLJK8grKi-kFS0AkESura5QamlpY2jvMB+QcDkqLH0wxYEw8ICSuFgAFd0uk4LByNR6Mx2IUeHdhKIns1ZN9BtYQVpRnJfl1JM55P1BnY1Ep9CpGpMoXM8MtVksUbRGNcuFiSriKs4CQNurYRgZ7BSGr1ASNupIzEo+kp3JChJgUPAyklMcV7sKEABadomRAmtQAhW2wE6VnQwjEA3Yh7lBDOSQUsxeqyaPoWYbWFSO9kHfwLV1CspPHSSHQ1ZyA1UKJzJlQ+iz+5oKewKWrfNyQ6FwhFI6NG2OINOSXDiypKAxtMyZi1dEE1Qk6L0FpTSUMl8OctaVnHVhC1+uDRvNhStin6XDaHQ9liSXTJiUa1xAA */
|
|
47
|
+
id: 'deploy',
|
|
48
|
+
initial: 'idle',
|
|
49
|
+
context: ({input}) => ({
|
|
50
|
+
disabled: false,
|
|
51
|
+
feedback: undefined,
|
|
52
|
+
label: undefined,
|
|
53
|
+
error: undefined,
|
|
54
|
+
deployHook: input.deployHook,
|
|
55
|
+
}),
|
|
56
|
+
states: {
|
|
57
|
+
idle: {
|
|
58
|
+
entry: assign({
|
|
59
|
+
feedback: () => undefined,
|
|
60
|
+
label: () => 'Deploy',
|
|
61
|
+
}),
|
|
62
|
+
on: {
|
|
63
|
+
DEPLOY: {
|
|
64
|
+
target: 'deploying',
|
|
65
|
+
},
|
|
34
66
|
},
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
67
|
+
},
|
|
68
|
+
deploying: {
|
|
69
|
+
entry: assign({
|
|
70
|
+
disabled: () => true,
|
|
71
|
+
label: () => 'Deploying',
|
|
72
|
+
}),
|
|
73
|
+
exit: assign({
|
|
74
|
+
disabled: () => false,
|
|
75
|
+
label: () => 'Deploy',
|
|
76
|
+
}),
|
|
77
|
+
invoke: {
|
|
78
|
+
src: 'deploy',
|
|
79
|
+
input: ({context}) => ({deployHook: context.deployHook}),
|
|
80
|
+
onDone: {
|
|
81
|
+
target: 'success',
|
|
44
82
|
},
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}),
|
|
54
|
-
invoke: {
|
|
55
|
-
onDone: {
|
|
56
|
-
target: 'success',
|
|
57
|
-
},
|
|
58
|
-
onError: {
|
|
59
|
-
target: 'error',
|
|
60
|
-
actions: assign({
|
|
61
|
-
error: (_context, event) => {
|
|
62
|
-
return event.data
|
|
63
|
-
},
|
|
64
|
-
}),
|
|
83
|
+
onError: {
|
|
84
|
+
target: 'error',
|
|
85
|
+
actions: assign({
|
|
86
|
+
error: ({event}) => {
|
|
87
|
+
if ('error' in event) {
|
|
88
|
+
return event.error as unknown as string
|
|
89
|
+
}
|
|
90
|
+
return 'Unknown error'
|
|
65
91
|
},
|
|
66
|
-
src: 'deploy',
|
|
67
|
-
},
|
|
68
|
-
},
|
|
69
|
-
success: {
|
|
70
|
-
entry: [assign({feedback: () => 'Succesfully started!'})],
|
|
71
|
-
exit: assign({
|
|
72
|
-
feedback: () => undefined,
|
|
73
92
|
}),
|
|
74
|
-
on: {
|
|
75
|
-
DEPLOY: 'deploying',
|
|
76
|
-
},
|
|
77
93
|
},
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
success: {
|
|
97
|
+
entry: assign({
|
|
98
|
+
feedback: () => 'Successfully started!',
|
|
99
|
+
}),
|
|
100
|
+
exit: assign({
|
|
101
|
+
feedback: () => undefined,
|
|
102
|
+
}),
|
|
103
|
+
on: {
|
|
104
|
+
DEPLOY: {
|
|
105
|
+
target: 'deploying',
|
|
82
106
|
},
|
|
83
107
|
},
|
|
84
108
|
},
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
return new Promise(async (resolve, reject) => {
|
|
90
|
-
try {
|
|
91
|
-
if (!deployHook) {
|
|
92
|
-
return reject(new Error('No deployHook URL defined'))
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
const res = await fetch(deployHook, {method: 'POST'})
|
|
96
|
-
const data = await res.json()
|
|
97
|
-
|
|
98
|
-
if (!res.ok) {
|
|
99
|
-
const errorMessage = (data?.error as Vercel.Error).message || res.statusText
|
|
100
|
-
return reject(errorMessage)
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return resolve()
|
|
104
|
-
} catch (err) {
|
|
105
|
-
console.error('Unable to deploy with error:', err)
|
|
106
|
-
return reject(new Error('Please check the developer console for more information'))
|
|
107
|
-
}
|
|
108
|
-
})
|
|
109
|
+
error: {
|
|
110
|
+
on: {
|
|
111
|
+
DEPLOY: {
|
|
112
|
+
target: 'deploying',
|
|
109
113
|
},
|
|
110
114
|
},
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
export default deployMachine
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
})
|