@@ -20,10 +20,114 @@ const path = require('path');
2020const fs = require ( 'fs' ) ;
2121
2222const CLERK_IOS_REPO = 'https://github.com/clerk/clerk-ios.git' ;
23- const CLERK_IOS_VERSION = '1.0.0' ;
23+ const CLERK_IOS_VERSION = '1.1.3' ;
24+ const CLERK_IOS_REQUIREMENT = {
25+ kind : 'exactVersion' ,
26+ version : CLERK_IOS_VERSION ,
27+ } ;
2428
2529const CLERK_MIN_IOS_VERSION = '17.0' ;
2630
31+ const normalizeRepositoryURL = repositoryURL => String ( repositoryURL || '' ) . replace ( / ^ " | " $ / g, '' ) ;
32+
33+ const isClerkIOSPackageReference = ref => normalizeRepositoryURL ( ref ?. repositoryURL ) === CLERK_IOS_REPO ;
34+
35+ const removeObjectReference = ( list , uuid ) => {
36+ if ( ! Array . isArray ( list ) ) {
37+ return ;
38+ }
39+
40+ for ( let index = list . length - 1 ; index >= 0 ; index -- ) {
41+ if ( list [ index ] ?. value === uuid ) {
42+ list . splice ( index , 1 ) ;
43+ }
44+ }
45+ } ;
46+
47+ const removeSwiftPackageProductDependencies = ( xcodeProject , packageUuids ) => {
48+ const productDependencies = xcodeProject . hash . project . objects . XCSwiftPackageProductDependency || { } ;
49+ const packageUuidSet = new Set ( packageUuids ) ;
50+
51+ for ( const [ productUuid , dependency ] of Object . entries ( productDependencies ) ) {
52+ if ( ! packageUuidSet . has ( dependency ?. package ) ) {
53+ continue ;
54+ }
55+
56+ delete productDependencies [ productUuid ] ;
57+
58+ const targets = xcodeProject . hash . project . objects . PBXNativeTarget || { } ;
59+ for ( const target of Object . values ( targets ) ) {
60+ removeObjectReference ( target ?. packageProductDependencies , productUuid ) ;
61+ }
62+ }
63+ } ;
64+
65+ const removeSwiftPackageReferences = ( xcodeProject , packageUuids ) => {
66+ const packageReferences = xcodeProject . hash . project . objects . XCRemoteSwiftPackageReference || { } ;
67+
68+ for ( const packageUuid of packageUuids ) {
69+ delete packageReferences [ packageUuid ] ;
70+ }
71+
72+ const projects = xcodeProject . hash . project . objects . PBXProject || { } ;
73+ for ( const project of Object . values ( projects ) ) {
74+ for ( const packageUuid of packageUuids ) {
75+ removeObjectReference ( project ?. packageReferences , packageUuid ) ;
76+ }
77+ }
78+
79+ removeSwiftPackageProductDependencies ( xcodeProject , packageUuids ) ;
80+ } ;
81+
82+ const findOrCreateClerkIOSPackageReference = xcodeProject => {
83+ const packageReferences = xcodeProject . hash . project . objects . XCRemoteSwiftPackageReference ;
84+ const existingEntries = Object . entries ( packageReferences ) . filter ( ( [ , ref ] ) => isClerkIOSPackageReference ( ref ) ) ;
85+
86+ if ( existingEntries . length > 0 ) {
87+ const [ uuid , ref ] = existingEntries [ 0 ] ;
88+ ref . repositoryURL = CLERK_IOS_REPO ;
89+ ref . requirement = { ...CLERK_IOS_REQUIREMENT } ;
90+
91+ const duplicateUuids = existingEntries . slice ( 1 ) . map ( ( [ duplicateUuid ] ) => duplicateUuid ) ;
92+ removeSwiftPackageReferences ( xcodeProject , duplicateUuids ) ;
93+
94+ return uuid ;
95+ }
96+
97+ const packageUuid = xcodeProject . generateUuid ( ) ;
98+ packageReferences [ packageUuid ] = {
99+ isa : 'XCRemoteSwiftPackageReference' ,
100+ repositoryURL : CLERK_IOS_REPO ,
101+ requirement : { ...CLERK_IOS_REQUIREMENT } ,
102+ } ;
103+ return packageUuid ;
104+ } ;
105+
106+ const findOrCreateSwiftPackageProductDependency = ( xcodeProject , packageUuid , productName ) => {
107+ const productDependencies = xcodeProject . hash . project . objects . XCSwiftPackageProductDependency ;
108+ const existingEntry = Object . entries ( productDependencies ) . find (
109+ ( [ , dep ] ) => dep ?. package === packageUuid && dep ?. productName === productName ,
110+ ) ;
111+
112+ if ( existingEntry ) {
113+ return existingEntry [ 0 ] ;
114+ }
115+
116+ const productUuid = xcodeProject . generateUuid ( ) ;
117+ productDependencies [ productUuid ] = {
118+ isa : 'XCSwiftPackageProductDependency' ,
119+ package : packageUuid ,
120+ productName,
121+ } ;
122+ return productUuid ;
123+ } ;
124+
125+ const addObjectReference = ( list , uuid , comment ) => {
126+ if ( ! list . some ( ref => ref . value === uuid ) ) {
127+ list . push ( { value : uuid , comment } ) ;
128+ }
129+ } ;
130+
27131const withClerkIOS = config => {
28132 console . log ( '✅ Clerk iOS plugin loaded' ) ;
29133
@@ -97,42 +201,21 @@ const withClerkIOS = config => {
97201 const targetUuid = targets . uuid ;
98202 const targetName = targets . name ;
99203
100- // Add Swift Package reference to the project
101- const packageUuid = xcodeProject . generateUuid ( ) ;
102204 const packageName = 'clerk-ios' ;
103205
104- // Add package reference to XCRemoteSwiftPackageReference section
105206 if ( ! xcodeProject . hash . project . objects . XCRemoteSwiftPackageReference ) {
106207 xcodeProject . hash . project . objects . XCRemoteSwiftPackageReference = { } ;
107208 }
108209
109- xcodeProject . hash . project . objects . XCRemoteSwiftPackageReference [ packageUuid ] = {
110- isa : 'XCRemoteSwiftPackageReference' ,
111- repositoryURL : CLERK_IOS_REPO ,
112- requirement : {
113- kind : 'exactVersion' ,
114- version : CLERK_IOS_VERSION ,
115- } ,
116- } ;
210+ const packageUuid = findOrCreateClerkIOSPackageReference ( xcodeProject ) ;
117211
118212 // Add package product dependencies (ClerkKit + ClerkKitUI)
119- const productUuidKit = xcodeProject . generateUuid ( ) ;
120- const productUuidKitUI = xcodeProject . generateUuid ( ) ;
121213 if ( ! xcodeProject . hash . project . objects . XCSwiftPackageProductDependency ) {
122214 xcodeProject . hash . project . objects . XCSwiftPackageProductDependency = { } ;
123215 }
124216
125- xcodeProject . hash . project . objects . XCSwiftPackageProductDependency [ productUuidKit ] = {
126- isa : 'XCSwiftPackageProductDependency' ,
127- package : packageUuid ,
128- productName : 'ClerkKit' ,
129- } ;
130-
131- xcodeProject . hash . project . objects . XCSwiftPackageProductDependency [ productUuidKitUI ] = {
132- isa : 'XCSwiftPackageProductDependency' ,
133- package : packageUuid ,
134- productName : 'ClerkKitUI' ,
135- } ;
217+ const productUuidKit = findOrCreateSwiftPackageProductDependency ( xcodeProject , packageUuid , 'ClerkKit' ) ;
218+ const productUuidKitUI = findOrCreateSwiftPackageProductDependency ( xcodeProject , packageUuid , 'ClerkKitUI' ) ;
136219
137220 // Add package to project's package references
138221 const projectSection = xcodeProject . hash . project . objects . PBXProject ;
@@ -143,40 +226,16 @@ const withClerkIOS = config => {
143226 project . packageReferences = [ ] ;
144227 }
145228
146- // Check if package is already added
147- const alreadyAdded = project . packageReferences . some ( ref => {
148- const refObj = xcodeProject . hash . project . objects . XCRemoteSwiftPackageReference [ ref . value ] ;
149- return refObj && refObj . repositoryURL === CLERK_IOS_REPO ;
150- } ) ;
151-
152- if ( ! alreadyAdded ) {
153- project . packageReferences . push ( {
154- value : packageUuid ,
155- comment : packageName ,
156- } ) ;
157- }
229+ addObjectReference ( project . packageReferences , packageUuid , packageName ) ;
158230
159231 // Add package products to main app target
160232 const nativeTarget = xcodeProject . hash . project . objects . PBXNativeTarget [ targetUuid ] ;
161233 if ( ! nativeTarget . packageProductDependencies ) {
162234 nativeTarget . packageProductDependencies = [ ] ;
163235 }
164236
165- const kitAlreadyAdded = nativeTarget . packageProductDependencies . some ( dep => dep . value === productUuidKit ) ;
166- if ( ! kitAlreadyAdded ) {
167- nativeTarget . packageProductDependencies . push ( {
168- value : productUuidKit ,
169- comment : 'ClerkKit' ,
170- } ) ;
171- }
172-
173- const kitUIAlreadyAdded = nativeTarget . packageProductDependencies . some ( dep => dep . value === productUuidKitUI ) ;
174- if ( ! kitUIAlreadyAdded ) {
175- nativeTarget . packageProductDependencies . push ( {
176- value : productUuidKitUI ,
177- comment : 'ClerkKitUI' ,
178- } ) ;
179- }
237+ addObjectReference ( nativeTarget . packageProductDependencies , productUuidKit , 'ClerkKit' ) ;
238+ addObjectReference ( nativeTarget . packageProductDependencies , productUuidKitUI , 'ClerkKitUI' ) ;
180239
181240 // Also add packages to ClerkExpo pod target if it exists
182241 const allTargets = xcodeProject . hash . project . objects . PBXNativeTarget ;
@@ -186,21 +245,8 @@ const withClerkIOS = config => {
186245 target . packageProductDependencies = [ ] ;
187246 }
188247
189- const podKitAdded = target . packageProductDependencies . some ( dep => dep . value === productUuidKit ) ;
190- if ( ! podKitAdded ) {
191- target . packageProductDependencies . push ( {
192- value : productUuidKit ,
193- comment : 'ClerkKit' ,
194- } ) ;
195- }
196-
197- const podKitUIAdded = target . packageProductDependencies . some ( dep => dep . value === productUuidKitUI ) ;
198- if ( ! podKitUIAdded ) {
199- target . packageProductDependencies . push ( {
200- value : productUuidKitUI ,
201- comment : 'ClerkKitUI' ,
202- } ) ;
203- }
248+ addObjectReference ( target . packageProductDependencies , productUuidKit , 'ClerkKit' ) ;
249+ addObjectReference ( target . packageProductDependencies , productUuidKitUI , 'ClerkKitUI' ) ;
204250
205251 console . log ( `✅ Added ClerkKit and ClerkKitUI packages to ClerkExpo pod target` ) ;
206252 }
@@ -716,4 +762,13 @@ const withClerkExpo = (config, props = {}) => {
716762} ;
717763
718764module . exports = withClerkExpo ;
719- module . exports . _testing = { validateThemeJson, isPlainObject, VALID_COLOR_KEYS , HEX_COLOR_REGEX } ;
765+ module . exports . _testing = {
766+ validateThemeJson,
767+ isPlainObject,
768+ VALID_COLOR_KEYS ,
769+ HEX_COLOR_REGEX ,
770+ CLERK_IOS_VERSION ,
771+ CLERK_IOS_REQUIREMENT ,
772+ findOrCreateClerkIOSPackageReference,
773+ findOrCreateSwiftPackageProductDependency,
774+ } ;
0 commit comments