@@ -15,20 +15,37 @@ setup('cleanup instances ', async () => {
1515 }
1616 const parsedPk = parsePublishableKey ( pk ) ;
1717 const apiUrl = isStaging ( parsedPk . frontendApi ) ? 'https://api.clerkstage.dev' : 'https://api.clerk.com' ;
18- return { secretKey, apiUrl } ;
18+ return {
19+ secretKey,
20+ apiUrl,
21+ instanceName : parsedPk . instanceId || parsedPk . frontendApi . split ( '.' ) [ 0 ] || 'unknown' ,
22+ } ;
1923 } )
2024 . filter ( Boolean ) ;
2125
22- const errors : Array < { instance : string ; error : Error ; operation : string } > = [ ] ;
26+ const cleanupSummary : Array < {
27+ instanceName : string ;
28+ usersDeleted : number ;
29+ orgsDeleted : number ;
30+ errors : string [ ] ;
31+ status : 'success' | 'error' | 'unauthorized' ;
32+ } > = [ ] ;
33+
34+ console . log ( '🧹 Starting E2E Test Cleanup Process...\n' ) ;
2335
2436 for ( const entry of entries ) {
25- const instanceKey = entry . secretKey . replace ( / ( s k _ ( t e s t | l i v e ) _ ) ( .+ ) ( ...) / , '$1***$4' ) ;
26- console . log ( `Cleanup for ${ instanceKey } ` ) ;
37+ const instanceSummary = {
38+ instanceName : entry . instanceName ,
39+ usersDeleted : 0 ,
40+ orgsDeleted : 0 ,
41+ errors : [ ] as string [ ] ,
42+ status : 'success' as 'success' | 'error' | 'unauthorized' ,
43+ } ;
2744
2845 try {
2946 const clerkClient = createClerkClient ( { secretKey : entry . secretKey , apiUrl : entry . apiUrl } ) ;
3047
31- // Get users
48+ // Get users with error handling
3249 let users : any [ ] = [ ] ;
3350 try {
3451 const { data : usersWithEmail } = await clerkClient . users . getUserList ( {
@@ -43,14 +60,19 @@ setup('cleanup instances ', async () => {
4360 limit : 150 ,
4461 } ) ;
4562
46- users = [ ...usersWithEmail , ...usersWithPhoneNumber ] ;
63+ // Deduplicate users by ID
64+ const allUsersMap = new Map ( ) ;
65+ [ ...usersWithEmail , ...usersWithPhoneNumber ] . forEach ( user => {
66+ allUsersMap . set ( user . id , user ) ;
67+ } ) ;
68+ users = Array . from ( allUsersMap . values ( ) ) ;
4769 } catch ( error ) {
48- errors . push ( { instance : instanceKey , error : error as Error , operation : 'getUserList' } ) ;
49- console . error ( `Error getting users for ${ instanceKey } :` , error ) ;
70+ instanceSummary . errors . push ( `Failed to get users: ${ error . message } ` ) ;
71+ console . error ( `Error getting users for ${ entry . instanceName } :` , error ) ;
5072 users = [ ] ; // Continue with empty users list
5173 }
5274
53- // Get organizations
75+ // Get organizations with error handling
5476 let orgs : any [ ] = [ ] ;
5577 try {
5678 const { data : orgsData } = await clerkClient . organizations . getOrganizationList ( {
@@ -63,16 +85,16 @@ setup('cleanup instances ', async () => {
6385 if ( isClerkAPIResponseError ( error ) && ( error . status === 404 || error . status === 403 ) ) {
6486 orgs = [ ] ;
6587 } else {
66- errors . push ( { instance : instanceKey , error : error as Error , operation : 'getOrganizationList' } ) ;
67- console . error ( `Error getting organizations for ${ instanceKey } :` , error ) ;
88+ instanceSummary . errors . push ( `Failed to get organizations: ${ error . message } ` ) ;
89+ console . error ( `Error getting organizations for ${ entry . instanceName } :` , error ) ;
6890 orgs = [ ] ; // Continue with empty orgs list
6991 }
7092 }
7193
7294 const usersToDelete = batchElements ( skipObjectsThatWereCreatedWithinTheLast10Minutes ( users ) , 5 ) ;
7395 const orgsToDelete = batchElements ( skipObjectsThatWereCreatedWithinTheLast10Minutes ( orgs ) , 5 ) ;
7496
75- // Delete users
97+ // Delete users with tracking
7698 for ( const batch of usersToDelete ) {
7799 console . log ( `Starting user deletion batch...` ) ;
78100 await Promise . all (
@@ -82,47 +104,94 @@ setup('cleanup instances ', async () => {
82104 user . createdAt ,
83105 ) . toISOString ( ) } )`,
84106 ) ;
85- return clerkClient . users . deleteUser ( user . id ) . catch ( error => {
86- console . error ( `Error deleting user ${ user . id } :` , error ) ;
87- } ) ;
107+ return clerkClient . users
108+ . deleteUser ( user . id )
109+ . then ( ( ) => {
110+ instanceSummary . usersDeleted ++ ;
111+ } )
112+ . catch ( error => {
113+ if ( error . status !== 404 ) {
114+ instanceSummary . errors . push ( `User ${ user . id } : ${ error . message } ` ) ;
115+ console . error ( `Error deleting user ${ user . id } :` , error ) ;
116+ }
117+ } ) ;
88118 } ) ,
89119 ) ;
90120 await new Promise ( r => setTimeout ( r , 1000 ) ) ;
91121 }
92122
93- // Delete organizations
123+ // Delete organizations with tracking
94124 for ( const batch of orgsToDelete ) {
95125 console . log ( `Starting organization deletion batch...` ) ;
96126 await Promise . all (
97127 batch . map ( org => {
98128 console . log ( `Cleaning up org ${ org . id } (${ org . name } ) (${ new Date ( org . createdAt ) . toISOString ( ) } )` ) ;
99- return clerkClient . organizations . deleteOrganization ( org . id ) . catch ( error => {
100- console . error ( `Error deleting org ${ org . id } :` , error ) ;
101- } ) ;
129+ return clerkClient . organizations
130+ . deleteOrganization ( org . id )
131+ . then ( ( ) => {
132+ instanceSummary . orgsDeleted ++ ;
133+ } )
134+ . catch ( error => {
135+ if ( error . status !== 404 ) {
136+ instanceSummary . errors . push ( `Org ${ org . id } : ${ error . message } ` ) ;
137+ console . error ( `Error deleting org ${ org . id } :` , error ) ;
138+ }
139+ } ) ;
102140 } ) ,
103141 ) ;
104142 await new Promise ( r => setTimeout ( r , 1000 ) ) ;
105143 }
144+
145+ // Report instance results
146+ const maskedKey = entry . secretKey . replace ( / ( s k _ ( t e s t | l i v e ) _ ) ( .+ ) ( ...) / , '$1***$4' ) ;
147+ if ( instanceSummary . usersDeleted > 0 || instanceSummary . orgsDeleted > 0 ) {
148+ console . log (
149+ `✅ ${ entry . instanceName } (${ maskedKey } ): ${ instanceSummary . usersDeleted } users, ${ instanceSummary . orgsDeleted } orgs deleted` ,
150+ ) ;
151+ } else {
152+ console . log ( `✅ ${ entry . instanceName } (${ maskedKey } ): clean` ) ;
153+ }
154+
155+ if ( instanceSummary . errors . length > 0 ) {
156+ instanceSummary . status = 'error' ;
157+ }
106158 } catch ( error ) {
107- errors . push ( { instance : instanceKey , error : error as Error , operation : 'general' } ) ;
108- console . error ( `General error during cleanup for ${ instanceKey } :` , error ) ;
159+ const maskedKey = entry . secretKey . replace ( / ( s k _ ( t e s t | l i v e ) _ ) ( .+ ) ( ...) / , '$1***$4' ) ;
160+ if ( isClerkAPIResponseError ( error ) && ( error . status === 401 || error . status === 403 ) ) {
161+ console . log ( `🔒 ${ entry . instanceName } (${ maskedKey } ): Unauthorized access` ) ;
162+ instanceSummary . status = 'unauthorized' ;
163+ } else {
164+ console . log ( `❌ ${ entry . instanceName } (${ maskedKey } ): ${ error . message } ` ) ;
165+ instanceSummary . errors . push ( error . message ) ;
166+ instanceSummary . status = 'error' ;
167+ }
109168 }
169+
170+ cleanupSummary . push ( instanceSummary ) ;
110171 }
111172
112- // Report all errors at the end
113- if ( errors . length > 0 ) {
114- console . log ( '\n=== CLEANUP ERRORS SUMMARY ===' ) ;
115- errors . forEach ( ( { instance, error, operation } ) => {
116- console . log ( `Instance: ${ instance } ` ) ;
117- console . log ( `Operation: ${ operation } ` ) ;
118- console . log ( `Error: ${ error . message } ` ) ;
119- if ( isClerkAPIResponseError ( error ) ) {
120- console . log ( `Status: ${ error . status } ` ) ;
121- }
122- console . log ( '---' ) ;
173+ // Final summary
174+ const totalUsersDeleted = cleanupSummary . reduce ( ( sum , instance ) => sum + instance . usersDeleted , 0 ) ;
175+ const totalOrgsDeleted = cleanupSummary . reduce ( ( sum , instance ) => sum + instance . orgsDeleted , 0 ) ;
176+ const errorInstances = cleanupSummary . filter ( instance => instance . status === 'error' ) . length ;
177+ const unauthorizedInstances = cleanupSummary . filter ( instance => instance . status === 'unauthorized' ) . length ;
178+
179+ console . log ( `\n📊 Summary: ${ totalUsersDeleted } users, ${ totalOrgsDeleted } orgs deleted` ) ;
180+ if ( errorInstances > 0 || unauthorizedInstances > 0 ) {
181+ console . log ( ` ${ errorInstances } errors, ${ unauthorizedInstances } unauthorized` ) ;
182+ }
183+
184+ // Detailed error report
185+ const instancesWithErrors = cleanupSummary . filter ( instance => instance . errors . length > 0 ) ;
186+ if ( instancesWithErrors . length > 0 ) {
187+ console . log ( '\n=== DETAILED ERROR REPORT ===' ) ;
188+ instancesWithErrors . forEach ( instance => {
189+ console . log ( `\n${ instance . instanceName } :` ) ;
190+ instance . errors . forEach ( error => console . log ( ` - ${ error } ` ) ) ;
123191 } ) ;
124- console . log ( `Total errors: ${ errors . length } ` ) ;
125- } else {
192+ }
193+
194+ if ( errorInstances === 0 && unauthorizedInstances === 0 ) {
126195 console . log ( '\n✅ Cleanup completed successfully with no errors' ) ;
127196 }
128197} ) ;
0 commit comments