@@ -8,6 +8,7 @@ public struct BKTConfig {
88 let eventsMaxQueueSize : Int
99 let pollingInterval : Int64
1010 let backgroundPollingInterval : Int64
11+ let sourceId : SourceID
1112 let sdkVersion : String
1213 let appVersion : String
1314 let logger : BKTLogger ?
@@ -22,6 +23,8 @@ public struct BKTConfig {
2223 private( set) var backgroundPollingInterval : Int64 ?
2324 private( set) var appVersion : String ?
2425 private( set) var logger : BKTLogger ?
26+ private( set) var wrapperSdkVersion : String ?
27+ private( set) var wrapperSdkSourceId : Int ?
2528
2629 public init ( ) { }
2730
@@ -65,6 +68,28 @@ public struct BKTConfig {
6568 return self
6669 }
6770
71+ // Sets the SDK version explicitly.
72+ // IMPORTANT: This option is intended for internal use only.
73+ // It should NOT be set by developers directly integrating this SDK.
74+ // Use this option ONLY when another SDK acts as a proxy and wraps this native SDK.
75+ // In such cases, set this value to the version of the proxy SDK.
76+ public func with( wrapperSdkVersion: String ) -> Builder {
77+ self . wrapperSdkVersion = wrapperSdkVersion
78+ return self
79+ }
80+
81+ // Sets the SDK sourceId explicitly.
82+ // IMPORTANT: This option is intended for internal use only.
83+ // It should NOT be set by developers directly integrating this SDK.
84+ // Use this option ONLY when another SDK acts as a proxy and wraps this native SDK.
85+ // In such cases, set this value to the sourceId of the proxy SDK.
86+ // The wrapperSdkSourceId is used to identify the origin of the request.
87+ // We don't expose the SourceID enum publicly because only Flutter and OpenFeature Swift are currently supported.
88+ public func with( wrapperSdkSourceId: Int ) -> Builder {
89+ self . wrapperSdkSourceId = wrapperSdkSourceId
90+ return self
91+ }
92+
6893 public func with( logger: BKTLogger ) -> Builder {
6994 self . logger = logger
7095 return self
@@ -91,27 +116,55 @@ extension BKTConfig {
91116 appVersion: String ,
92117 logger: BKTLogger ? = nil
93118 ) throws {
94- guard !apiKey. isEmpty else {
119+ // Delegate to Builder to keep a single validation/normalization path.
120+ let builder = BKTConfig . Builder ( )
121+ . with ( apiKey: apiKey)
122+ . with ( apiEndpoint: apiEndpoint)
123+ . with ( featureTag: featureTag)
124+ . with ( eventsFlushInterval: eventsFlushInterval)
125+ . with ( eventsMaxQueueSize: eventsMaxQueueSize)
126+ . with ( pollingInterval: pollingInterval)
127+ . with ( backgroundPollingInterval: backgroundPollingInterval)
128+ . with ( appVersion: appVersion)
129+ if let logger = logger {
130+ _ = builder. with ( logger: logger)
131+ }
132+ // Build and assign to self
133+ self = try builder. build ( )
134+ }
135+
136+ private init ( with builder: Builder ) throws {
137+ guard let apiKey = builder. apiKey, apiKey. isNotEmpty ( ) else {
95138 throw BKTError . illegalArgument ( message: " apiKey is required " )
96139 }
97- guard let apiEndpointURL = URL ( string: apiEndpoint) else {
140+ guard let apiEndpoint = builder . apiEndpoint , apiEndpoint . isNotEmpty ( ) , let apiEndpointURL = URL ( string: apiEndpoint) else {
98141 throw BKTError . illegalArgument ( message: " apiEndpoint is required " )
99142 }
100- guard ! appVersion. isEmpty else {
143+ guard let appVersion = builder . appVersion , appVersion . isNotEmpty ( ) else {
101144 throw BKTError . illegalArgument ( message: " appVersion is required " )
102145 }
103146
104- var pollingInterval = pollingInterval
147+ // refs: JS SDK PR https://github.com/bucketeer-io/javascript-client-sdk/pull/91
148+ // Allow Builder.featureTag to be nil
149+ // So the default value of the BKTConfig will be ""
150+ let featureTag = builder. featureTag ?? " "
151+ let logger = builder. logger
152+ // Set default intervals if needed
153+ var pollingInterval : Int64 = builder. pollingInterval ?? Constant . MINIMUM_POLLING_INTERVAL_MILLIS
154+ var backgroundPollingInterval : Int64 = builder. backgroundPollingInterval ?? Constant . MINIMUM_BACKGROUND_POLLING_INTERVAL_MILLIS
155+ var eventsFlushInterval : Int64 = builder. eventsFlushInterval ?? Constant . DEFAULT_FLUSH_INTERVAL_MILLIS
156+ let eventsMaxQueueSize = builder. eventsMaxQueueSize ?? Constant . DEFAULT_MAX_QUEUE_SIZE
157+
105158 if pollingInterval < Constant . MINIMUM_POLLING_INTERVAL_MILLIS {
106159 logger? . warn ( message: " pollingInterval: \( pollingInterval) is set but must be above \( Constant . MINIMUM_POLLING_INTERVAL_MILLIS) " )
107160 pollingInterval = Constant . MINIMUM_POLLING_INTERVAL_MILLIS
108161 }
109- var backgroundPollingInterval = backgroundPollingInterval
162+
110163 if backgroundPollingInterval < Constant . MINIMUM_BACKGROUND_POLLING_INTERVAL_MILLIS {
111164 logger? . warn ( message: " backgroundPollingInterval: \( backgroundPollingInterval) is set but must be above \( Constant . MINIMUM_BACKGROUND_POLLING_INTERVAL_MILLIS) " )
112165 backgroundPollingInterval = Constant . MINIMUM_BACKGROUND_POLLING_INTERVAL_MILLIS
113166 }
114- var eventsFlushInterval = eventsFlushInterval
167+
115168 if eventsFlushInterval < Constant . MINIMUM_FLUSH_INTERVAL_MILLIS {
116169 logger? . warn ( message: " eventsFlushInterval: \( eventsFlushInterval) is set but must be above \( Constant . MINIMUM_FLUSH_INTERVAL_MILLIS) " )
117170 eventsFlushInterval = Constant . DEFAULT_FLUSH_INTERVAL_MILLIS
@@ -123,42 +176,46 @@ extension BKTConfig {
123176 self . eventsMaxQueueSize = eventsMaxQueueSize
124177 self . pollingInterval = pollingInterval
125178 self . backgroundPollingInterval = backgroundPollingInterval
126- self . sdkVersion = Version . current
179+
180+ let resolvedSdkSourceId = try resolveSdkSourceId ( wrapperSdkSourceId: builder. wrapperSdkSourceId)
181+ let resolvedSdkVersion = try resolveSdkVersion (
182+ resolvedSdkSourceId: resolvedSdkSourceId,
183+ wrapperSdkVersion: builder. wrapperSdkVersion
184+ )
185+
186+ self . sourceId = resolvedSdkSourceId
187+ self . sdkVersion = resolvedSdkVersion
127188 self . appVersion = appVersion
128189 self . logger = logger
129190 }
130191
131- private init ( with builder: Builder ) throws {
132- guard let apiKey = builder. apiKey, apiKey. isNotEmpty ( ) else {
133- throw BKTError . illegalArgument ( message: " apiKey is required " )
134- }
135- guard let apiEndpoint = builder. apiEndpoint, apiEndpoint. isNotEmpty ( ) else {
136- throw BKTError . illegalArgument ( message: " apiEndpoint is required " )
137- }
138- guard let appVersion = builder. appVersion, appVersion. isNotEmpty ( ) else {
139- throw BKTError . illegalArgument ( message: " appVersion is required " )
140- }
192+ func toSDKInfo( ) -> SDKInfo {
193+ return . init( sourceId: self . sourceId, sdkVersion: self . sdkVersion)
194+ }
195+ }
141196
142- // Set default intervals if needed
143- let pollingInterval : Int64 = builder. pollingInterval ?? Constant . MINIMUM_POLLING_INTERVAL_MILLIS
144- let backgroundPollingInterval : Int64 = builder. backgroundPollingInterval ?? Constant . MINIMUM_BACKGROUND_POLLING_INTERVAL_MILLIS
145- let eventsFlushInterval : Int64 = builder. eventsFlushInterval ?? Constant . DEFAULT_FLUSH_INTERVAL_MILLIS
146- let eventsMaxQueueSize = builder. eventsMaxQueueSize ?? Constant . DEFAULT_MAX_QUEUE_SIZE
197+ // Only Flutter (8) and OpenFeature Swift (101) are supported currently.
198+ // Other source IDs will throw an error as its not from iOS
199+ private let supportedWrapperSdkSourceIds : [ SourceID ] = [ . flutter, . openFeatureSwift]
147200
148- // Use the current init method
149- try self . init ( apiKey: apiKey,
150- apiEndpoint: apiEndpoint,
151- // refs: JS SDK PR https://github.com/bucketeer-io/javascript-client-sdk/pull/91
152- // Allow Builder.featureTag could be nill
153- // So the default value of the BKTConfig will be ""
154- featureTag: builder. featureTag ?? " " ,
155- eventsFlushInterval: eventsFlushInterval,
156- eventsMaxQueueSize: eventsMaxQueueSize,
157- pollingInterval: pollingInterval,
158- backgroundPollingInterval: backgroundPollingInterval,
159- appVersion: appVersion,
160- logger: builder. logger)
201+ private func resolveSdkSourceId( wrapperSdkSourceId: Int ? ) throws -> SourceID {
202+ guard let wrapperSdkSourceId = wrapperSdkSourceId else {
203+ return . ios // default ios
204+ }
205+ if let sourceId = SourceID ( rawValue: wrapperSdkSourceId) , supportedWrapperSdkSourceIds. contains ( sourceId) {
206+ return sourceId
207+ }
208+ throw BKTError . illegalArgument ( message: " Unsupported wrapperSdkSourceId: \( wrapperSdkSourceId) " )
209+ }
210+
211+ private func resolveSdkVersion( resolvedSdkSourceId: SourceID , wrapperSdkVersion: String ? ) throws -> String {
212+ if resolvedSdkSourceId != . ios {
213+ if let wrapperSdkVersion = wrapperSdkVersion, wrapperSdkVersion. isNotEmpty ( ) {
214+ return wrapperSdkVersion
215+ }
216+ throw BKTError . illegalArgument ( message: " wrapperSdkVersion is required when sourceId is not iOS " )
161217 }
218+ return Version . current
162219}
163220
164221fileprivate extension String {
0 commit comments