@@ -4,37 +4,27 @@ import Joi from "joi"
44
55import { Issue } from "./types"
66
7- export const syncIssue = async ( {
8- issue,
9- graphql : gql ,
10- project,
11- organization,
12- } : {
13- issue : Issue
14- graphql : typeof OctokitGraphQL
15- project : { number : number ; targetField : string ; targetValue : string }
16- organization : string
17- } ) => {
18- /*
19-
20- Step: Fetch the project's data so that we'll be able to create an item on it
21- for the issue given as input
22-
23- */
24- const projectData = await gql < {
25- organization : {
26- projectNext : {
27- id : string
28- fields : {
29- nodes : {
30- id : string
31- name : string
32- settings ?: string | null
33- } [ ]
34- }
7+ type ProjectData = {
8+ organization : {
9+ projectNext : {
10+ id : string
11+ fields : {
12+ nodes : {
13+ id : string
14+ name : string
15+ settings ?: string | null
16+ } [ ]
3517 }
3618 }
37- } > (
19+ }
20+ }
21+
22+ const fetchProjectData : ( params : {
23+ gql : typeof OctokitGraphQL
24+ organization : string
25+ number : number
26+ } ) => Promise < ProjectData > = ( { gql, organization, number } ) => {
27+ return gql < ProjectData > (
3828 `
3929 query($organization: String!, $number: Int!) {
4030 organization(login: $organization){
@@ -51,29 +41,34 @@ export const syncIssue = async ({
5141 }
5242 }
5343 ` ,
54- { organization, number : project . number } ,
44+ { organization, number } ,
5545 )
46+ }
5647
57- /*
58-
59- Step: Find the target field which we were given as input
48+ const resolveProjectTargetField : ( params : {
49+ projectData : ProjectData
50+ targetField : string
51+ targetValue : string
52+ } ) => { targetFieldId : string ; targetValueId : string } = ( {
53+ projectData,
54+ targetField,
55+ targetValue,
56+ } ) => {
57+ const targetFieldNode =
58+ projectData . organization . projectNext . fields . nodes . find (
59+ ( { name } ) => name === targetField ,
60+ )
6061
61- */
62- const targetField = projectData . organization . projectNext . fields . nodes . find (
63- ( { name } ) => {
64- return name === project . targetField
65- } ,
66- )
6762 assert (
68- targetField ,
69- `No field named "${ project . targetField } " was found in the project` ,
63+ targetFieldNode ,
64+ `No field named "${ targetField } " was found in the project` ,
7065 )
7166
7267 assert (
73- targetField . settings ,
74- `Settings for the field "${ project . targetField } " are empty` ,
68+ targetFieldNode . settings ,
69+ `Settings for the field "${ targetField } " are empty` ,
7570 )
76- const parsedSettings = JSON . parse ( targetField . settings )
71+ const parsedSettings = JSON . parse ( targetFieldNode . settings )
7772
7873 const settingsValidator = Joi . object < {
7974 options : [ { id : string ; name : string } ]
@@ -91,28 +86,34 @@ export const syncIssue = async ({
9186 assert ( settingsResult . error === undefined , settingsResult . error )
9287 const { value : settings } = settingsResult
9388
94- /*
95-
96- Step: Find the target value given as input in the possible values for the
97- target field
98-
99- */
100- const targetValue = settings . options . find ( ( { name } ) => {
101- return name === project . targetValue
89+ const targetValueNode = settings . options . find ( ( { name } ) => {
90+ return name === targetValue
10291 } )
10392 assert (
104- targetValue ,
105- `No value named "${ project . targetValue } " was found for the "${ project . targetField } " field` ,
93+ targetValueNode ,
94+ `No value named "${ targetValue } " was found for the "${ targetField } " field` ,
10695 )
10796
108- /*
97+ return {
98+ targetFieldId : targetFieldNode . id ,
99+ targetValueId : targetValueNode . id ,
100+ }
101+ }
109102
110- Step: Create an item for the issue in the board
103+ type CreatedProjectItemForIssue = {
104+ addProjectNextItem : { projectNextItem : { id : string } }
105+ }
111106
112- */
113- const createItemResult = await gql < {
114- addProjectNextItem : { projectNextItem : { id : string } }
115- } > (
107+ const createProjectItemForIssue : ( params : {
108+ gql : typeof OctokitGraphQL
109+ projectId : string
110+ issueNodeId : string
111+ } ) => Promise < CreatedProjectItemForIssue > = ( {
112+ gql,
113+ projectId,
114+ issueNodeId,
115+ } ) => {
116+ return gql < CreatedProjectItemForIssue > (
116117 `
117118 mutation($project: ID!, $issue: ID!) {
118119 addProjectNextItem(input: {projectId: $project, contentId: $issue}) {
@@ -122,17 +123,24 @@ export const syncIssue = async ({
122123 }
123124 }
124125 ` ,
125- { project : projectData . organization . projectNext . id , issue : issue . nodeId } ,
126+ { project : projectId , issue : issueNodeId } ,
126127 )
128+ }
127129
128- /*
129-
130- Step: Assign the issue to the target field and value we were given as input
131- Apparently it's not (yet?) possible to provide this assignment in the
132- initial mutation, hence why two separate requests are made.
133-
134- */
135- await gql (
130+ const updateProjectNextItemField : ( params : {
131+ gql : typeof OctokitGraphQL
132+ project : string
133+ item : string
134+ targetField : string
135+ targetFieldValue : string
136+ } ) => Promise < void > = ( {
137+ gql,
138+ project,
139+ item,
140+ targetField,
141+ targetFieldValue,
142+ } ) => {
143+ return gql (
136144 `
137145 mutation (
138146 $project: ID!
@@ -152,11 +160,54 @@ export const syncIssue = async ({
152160 }
153161 }
154162 ` ,
155- {
156- project : projectData . organization . projectNext . id ,
157- item : createItemResult . addProjectNextItem . projectNextItem . id ,
158- targetField : targetField . id ,
159- targetFieldValue : targetValue . id ,
160- } ,
163+ { project, item, targetField, targetFieldValue } ,
161164 )
162165}
166+
167+ export const syncIssue = async ( {
168+ issue,
169+ graphql : gql ,
170+ project,
171+ organization,
172+ } : {
173+ issue : Issue
174+ graphql : typeof OctokitGraphQL
175+ project : { number : number ; targetField ?: string ; targetValue ?: string }
176+ organization : string
177+ } ) => {
178+ const projectData = await fetchProjectData ( {
179+ gql,
180+ organization,
181+ number : project . number ,
182+ } )
183+
184+ const targetField =
185+ project . targetField && project . targetValue
186+ ? resolveProjectTargetField ( {
187+ projectData,
188+ targetField : project . targetField ,
189+ targetValue : project . targetValue ,
190+ } )
191+ : null
192+
193+ const createdProjectItemForIssue = await createProjectItemForIssue ( {
194+ gql,
195+ projectId : projectData . organization . projectNext . id ,
196+ issueNodeId : issue . nodeId ,
197+ } )
198+
199+ if ( targetField !== null ) {
200+ /*
201+ Assign the issue to the target field and value we were given as input
202+ Apparently it's not (yet?) possible to provide this assignment in the
203+ initial mutation, hence why two separate requests are made.
204+ */
205+ await updateProjectNextItemField ( {
206+ gql,
207+ project : projectData . organization . projectNext . id ,
208+ item : createdProjectItemForIssue . addProjectNextItem . projectNextItem . id ,
209+ targetField : targetField . targetFieldId ,
210+ targetFieldValue : targetField . targetValueId ,
211+ } )
212+ }
213+ }
0 commit comments