1
- import db , { Prisma } from "db"
1
+ import db , { Checklist , ChecklistItem , Prisma } from "db"
2
+ import { r } from "vitest/dist/index-9f5bc072"
2
3
import { z } from "zod"
3
4
4
5
const ChecklistItemObjectSchema = z . object ( {
@@ -20,7 +21,9 @@ export type ChecklistSeedDataType = z.infer<typeof ChecklistSchema>
20
21
21
22
export const ChecklistsSchema = z . array ( ChecklistSchema )
22
23
23
- export const updateChecklistsInPlace = async ( checklistData : ChecklistSeedDataType ) => {
24
+ export const updateChecklistsInPlace = async (
25
+ checklistData : ChecklistSeedDataType
26
+ ) => {
24
27
console . log ( `Updating checklist: ${ checklistData . name } ` )
25
28
26
29
let checklist = await db . checklist . findFirst ( {
@@ -30,7 +33,11 @@ export const updateChecklistsInPlace = async (checklistData: ChecklistSeedDataTy
30
33
} )
31
34
32
35
if ( checklist === null ) {
33
- throw new Error ( `Attempted to update a checklist, but it wasn't found: ${ checklistData . name } ` )
36
+ console . warn ( `Checklist not found: ${ checklistData . name } . Creating now.` )
37
+ checklist = await db . checklist . create ( {
38
+ data : { name : checklistData . name , version : checklistData . version } ,
39
+ include : { checklistItems : true } ,
40
+ } )
34
41
}
35
42
36
43
checklist = await db . checklist . update ( {
@@ -40,85 +47,135 @@ export const updateChecklistsInPlace = async (checklistData: ChecklistSeedDataTy
40
47
} )
41
48
42
49
if ( checklist === null ) {
43
- throw new Error ( `Checklist found but not returned by the updater: ${ checklistData . name } ` )
50
+ throw new Error (
51
+ `Checklist found but not returned by the updater: ${ checklistData . name } `
52
+ )
44
53
}
45
54
46
- // collect data for later bulk operations
47
- const newChecklistItemsData : Prisma . ChecklistItemCreateManyInput [ ] = [ ]
48
- const newUserChecklistItemsData : Prisma . UserChecklistItemCreateManyInput [ ] = [ ]
55
+ const checklistItemCreateManyInput : Prisma . ChecklistItemCreateManyInput [ ] = [ ]
49
56
for ( let i = 0 ; i < checklistData . items . length ; i ++ ) {
50
57
const item = checklistData . items [ i ]
51
58
const itemData = ChecklistItemObjectSchema . parse (
52
59
typeof item === "string" ? { displayText : item } : item
53
60
)
54
61
55
- const existingItem = checklist . checklistItems . find (
56
- ( ci ) => ci . displayText === itemData . displayText
57
- )
58
-
59
- if ( existingItem ) {
60
- await db . checklistItem . update ( {
61
- where : { id : existingItem . id } ,
62
- data : { ...itemData , displayIndex : i } ,
63
- } )
64
- } else {
65
- newChecklistItemsData . push ( {
66
- ...itemData ,
67
- checklistId : checklist . id ,
68
- displayIndex : i ,
69
- } )
70
- }
62
+ checklistItemCreateManyInput . push ( {
63
+ ...itemData ,
64
+ checklistId : checklist . id ,
65
+ displayIndex : i ,
66
+ } )
71
67
}
72
68
73
69
console . log ( `Done updating existing items for: ${ checklistData . name } ` )
74
70
await db . checklistItem . createMany ( {
75
- data : newChecklistItemsData ,
71
+ data : checklistItemCreateManyInput ,
72
+ skipDuplicates : true ,
76
73
} )
77
74
console . log ( `Done creating new items for: ${ checklistData . name } ` )
78
- // TODO: remove obsolete ChecklistItems
79
- await updateUserChecklists ( checklist . id , newChecklistItemsData )
80
- console . log ( `Done updating UserChecklistItems for: ${ checklistData . name } ` )
81
- // TODO: remove obsolete UserChecklistItems
75
+
76
+ const checklistItems = await deleteObsoleteChecklistItems (
77
+ checklist ,
78
+ checklistItemCreateManyInput
79
+ )
80
+ console . log ( `deleteObsoleteChecklistItems done for: ${ checklistData . name } ` )
81
+ await updateUserChecklists ( checklist , checklistItems )
82
+ console . log ( `updateUserChecklists done for: ${ checklistData . name } ` )
82
83
83
84
return checklist
84
85
}
85
86
86
87
const updateUserChecklists = async (
87
- checklistId : number ,
88
- newChecklistItemsData : Prisma . ChecklistItemCreateManyInput [ ]
88
+ checklist : Checklist ,
89
+ checklistItems : ChecklistItem [ ]
89
90
) => {
90
- const createdChecklistItems = await db . checklistItem . findMany ( {
91
+ const userChecklists = await db . userChecklist . findMany ( {
91
92
where : {
92
- checklistId : checklistId ,
93
- displayText : { in : newChecklistItemsData . map ( ( item ) => item . displayText ) } ,
93
+ checklistId : checklist . id ,
94
94
} ,
95
95
} )
96
96
97
- const displayTextToIdMap = createdChecklistItems . reduce ( ( acc , item ) => {
98
- acc [ item . displayText ] = item . id
99
- return acc
100
- } , { } as Record < string , number > )
101
-
102
- // Prepare UserChecklistItems for bulk creation or update
103
- const newUserChecklistItemsData : Prisma . UserChecklistItemCreateManyInput [ ] = [ ]
104
- const userChecklists = await db . userChecklist . findMany ( {
105
- where : { checklistId : checklistId } ,
106
- } )
107
- for ( const newItem of newChecklistItemsData ) {
108
- const checklistItemId = displayTextToIdMap [ newItem . displayText ]
109
- if ( checklistItemId === undefined ) continue
97
+ for ( const userChecklist of userChecklists ) {
98
+ await db . userChecklistItem . deleteMany ( {
99
+ where : {
100
+ userChecklistId : userChecklist . id ,
101
+ } ,
102
+ } )
110
103
111
- userChecklists . forEach ( ( userChecklist ) => {
112
- newUserChecklistItemsData . push ( {
104
+ await db . userChecklistItem . createMany ( {
105
+ data : checklistItems . map ( ( itemData ) => ( {
113
106
userChecklistId : userChecklist . id ,
107
+ checklistItemId : itemData . id ,
114
108
userId : userChecklist . userId ,
115
- checklistItemId : checklistItemId ,
116
- isComplete : false ,
117
- } )
109
+ } ) ) ,
118
110
} )
119
111
}
112
+ }
120
113
121
- await db . userChecklistItem . createMany ( {
122
- data : newUserChecklistItemsData ,
114
+ const deleteObsoleteChecklistItems = async (
115
+ checklist : Checklist & { checklistItems : ChecklistItem [ ] } ,
116
+ newChecklistItemsData : Prisma . ChecklistItemCreateManyInput [ ]
117
+ ) : Promise < ChecklistItem [ ] > => {
118
+ const checklistItemsWithIds = await db . checklistItem . findMany ( {
119
+ where : {
120
+ checklistId : checklist . id ,
121
+ } ,
122
+ } )
123
+
124
+ const newItemsSet = new Set (
125
+ newChecklistItemsData . map ( ( item ) => {
126
+ return (
127
+ item . displayText +
128
+ item . detailText +
129
+ item . isRequired +
130
+ item . linkText +
131
+ item . linkUri
132
+ )
133
+ } )
134
+ )
135
+
136
+ const obsoleteChecklistItems : ChecklistItem [ ] =
137
+ checklist . checklistItems . filter ( ( item ) => {
138
+ const currCompoundKey =
139
+ item . displayText +
140
+ item . detailText +
141
+ item . isRequired +
142
+ item . linkText +
143
+ item . linkUri
144
+
145
+ return ! newItemsSet . has ( currCompoundKey )
146
+ } )
147
+
148
+ if ( obsoleteChecklistItems . length > 0 ) {
149
+ const idsToDelete = obsoleteChecklistItems . map ( ( item ) => item . id )
150
+ await db . userChecklistItem . deleteMany ( {
151
+ where : {
152
+ checklistItemId : {
153
+ in : idsToDelete ,
154
+ } ,
155
+ } ,
156
+ } )
157
+ await db . checklistItem . deleteMany ( {
158
+ where : {
159
+ id : {
160
+ in : idsToDelete ,
161
+ } ,
162
+ } ,
163
+ } )
164
+ }
165
+
166
+ const countOfItemsAfterDeletion = await db . checklistItem . count ( {
167
+ where : {
168
+ checklistId : checklist . id ,
169
+ } ,
123
170
} )
171
+
172
+ if ( countOfItemsAfterDeletion !== newChecklistItemsData . length ) {
173
+ throw new Error (
174
+ `Checklist items count mismatch for: ${ checklist . name } .\n` +
175
+ `Expected: ${ newChecklistItemsData . length } , ` +
176
+ `Found: ${ countOfItemsAfterDeletion } `
177
+ )
178
+ }
179
+
180
+ return checklistItemsWithIds
124
181
}
0 commit comments