11//
22// File.swift
3- //
3+ //
44//
55// Created by Brandon Sneed on 5/5/22.
66//
@@ -14,8 +14,6 @@ public class AnalyticsJS: JSExport {
1414
1515 internal weak var analytics : Analytics ?
1616
17- internal var addedPlugins = [ ( String? , LivePlugin) ] ( )
18-
1917 internal lazy var currentLivePluginVersion : String ? = {
2018 return LivePlugins . currentLivePluginVersion ( )
2119 } ( )
@@ -36,9 +34,13 @@ public class AnalyticsJS: JSExport {
3634 Self . existingInstances. removeAll ( where: { $0 === self . analytics } )
3735 }
3836
37+
3938 static func insertOrigin( event: RawEvent ? , data: [ String : Any ] ) -> RawEvent ? {
4039 guard var working = event else { return event }
41- if let newContext = try ? working. context? . add ( value: data, forKey: " __eventOrigin " ) {
40+ if let newContext = try ? working. context? . add (
41+ value: data,
42+ forKey: " __eventOrigin "
43+ ) {
4244 working. context = newContext
4345 }
4446 return working
@@ -51,45 +53,76 @@ public class AnalyticsJS: JSExport {
5153 ] )
5254 }
5355
56+ private func contextEnrichment( with context: [ String : Any ] ? ) -> EnrichmentClosure {
57+ return { event in
58+ guard var working = event, let context = context else {
59+ return event
60+ }
61+
62+ // Get existing context as dictionary and merge with new context
63+ var mergedContext = working. context? . dictionaryValue ?? [ : ]
64+ mergedContext. merge ( context) { _, new in new }
65+
66+ do {
67+ working. context = try JSON ( mergedContext)
68+ } catch {
69+ // If JSON creation fails, return original event
70+ return event
71+ }
72+ return working
73+ }
74+ }
75+
76+ private func enrichments( with context: [ String : Any ] ? ) -> [ EnrichmentClosure ] {
77+ var enrichments = [ originMarkerEnrichment]
78+ if let context = context {
79+ enrichments. append ( contextEnrichment ( with: context) )
80+ }
81+ return enrichments
82+ }
83+
5484 internal func setupExports( ) {
5585 exportProperty ( named: " traits " ) { [ weak self] in
56- guard let self else { return nil }
57- let traits : [ String : Any ] ? = analytics? . traits ( )
86+ guard let self, let analytics = self . analytics else { return nil }
87+ let traits : [ String : Any ] ? = analytics. traits ( )
5888 return traits as? JSConvertible
5989 }
6090
6191 exportProperty ( named: " userId " ) { [ weak self] in
62- guard let self else { return nil }
63- return analytics? . userId
92+ return self ? . analytics? . userId
6493 }
6594
6695 exportProperty ( named: " anonymousId " ) { [ weak self] in
67- guard let self else { return nil }
68- return analytics? . anonymousId
96+ return self ? . analytics? . anonymousId
6997 }
7098
7199 exportMethod ( named: " track " ) { [ weak self] in self ? . track ( args: $0) }
72- exportMethod ( named: " identify " ) { [ weak self] in self ? . identify ( args: $0) }
100+ exportMethod ( named: " identify " ) {
101+ [ weak self] in self ? . identify ( args: $0)
102+ }
73103 exportMethod ( named: " screen " ) { [ weak self] in self ? . screen ( args: $0) }
74104 exportMethod ( named: " group " ) { [ weak self] in self ? . group ( args: $0) }
75- exportMethod ( named: " alias " ) { [ weak self] in self ? . alias ( args: $0) }
76105 exportMethod ( named: " add " ) { [ weak self] in self ? . add ( args: $0) }
77106 exportMethod ( named: " flush " ) { [ weak self] in self ? . flush ( args: $0) }
78107 exportMethod ( named: " reset " ) { [ weak self] in self ? . reset ( args: $0) }
79- exportMethod ( named: " removeLivePlugins " ) { [ weak self] in self ? . removeLivePlugins ( args: $0) }
80108 }
81109
82110 public override func construct( args: [ JSConvertible ? ] ) {
83111 if let writeKey = args. typed ( as: String . self, index: 0 ) {
84- let existing = Self . existingInstances. first ( where: { $0. writeKey == writeKey } )
112+ let existing = Self . existingInstances. first (
113+ where: { $0. writeKey == writeKey
114+ } )
85115 if let existing {
86116 self . analytics = existing
87117 return
88118 } else {
89119 // we do some work on user-created instances to avoid multiple instances of the same write key
90120 // by just attaching whatever existing instance that might exist with that write key.
91- let createdAnalytics = Analytics ( configuration: Configuration ( writeKey: writeKey)
92- . trackApplicationLifecycleEvents ( false )
121+ let createdAnalytics = Analytics (
122+ configuration: Configuration (
123+ writeKey: writeKey
124+ )
125+ . setTrackedApplicationLifecycleEvents ( . none)
93126 )
94127 Self . existingInstances. append ( createdAnalytics)
95128 self . analytics = createdAnalytics
@@ -99,113 +132,109 @@ public class AnalyticsJS: JSExport {
99132
100133 public func track( args: [ JSConvertible ? ] ) -> JSConvertible ? {
101134 guard let analytics else { return nil }
102- guard let name = args. typed ( as: String . self, index: 0 ) else { return nil }
103- let properties = args. typed ( as: Dictionary . self, index: 1 )
104-
105- let addEventOrigin : EnrichmentClosure = { [ weak self] event in
106- return Self . insertOrigin ( event: event, data: [
107- " type " : " signals " ,
108- " version " : self ? . currentLivePluginVersion ?? " "
109- ] )
135+ guard let name = args. typed ( as: String . self, index: 0 ) else {
136+ return nil
110137 }
138+ let properties = args. typed ( as: Dictionary . self, index: 1 )
139+ let context = args. typed ( as: Dictionary . self, index: 2 )
111140
112- analytics. track ( name: name, properties: properties, enrichments: [ addEventOrigin] )
141+ analytics
142+ . track (
143+ name: name,
144+ properties: properties,
145+ enrichments: enrichments ( with: context)
146+ )
113147 return nil
114148 }
115149
116150 public func identify( args: [ JSConvertible ? ] ) -> JSConvertible ? {
117151 guard let analytics else { return nil }
118- guard let userId = args. typed ( as: String . self, index: 0 ) else { return nil }
152+ guard let userId = args. typed ( as: String . self, index: 0 ) else {
153+ return nil
154+ }
119155 let traits = args. typed ( as: Dictionary . self, index: 1 )
120- analytics. identify ( userId: userId, traits: traits, enrichments: [ originMarkerEnrichment] )
156+ let context = args. typed ( as: Dictionary . self, index: 2 )
157+ analytics
158+ . identify (
159+ userId: userId,
160+ traits: traits,
161+ enrichments: enrichments ( with: context)
162+ )
121163 return nil
122164 }
123165
124166 public func screen( args: [ JSConvertible ? ] ) -> JSConvertible ? {
125167 guard let analytics else { return nil }
126- guard let title = args. typed ( as: String . self, index: 0 ) else { return nil }
168+ guard let title = args. typed ( as: String . self, index: 0 ) else {
169+ return nil
170+ }
127171 let category = args. typed ( as: String . self, index: 1 )
128172 let properties = args. typed ( as: Dictionary . self, index: 2 )
129- analytics. screen ( title: title, category: category, properties: properties, enrichments: [ originMarkerEnrichment] )
173+ let context = args. typed ( as: Dictionary . self, index: 3 )
174+ analytics
175+ . screen (
176+ title: title,
177+ category: category,
178+ properties: properties,
179+ enrichments: enrichments ( with: context)
180+ )
130181 return nil
182+
131183 }
132184
133185 public func group( args: [ JSConvertible ? ] ) -> JSConvertible ? {
134186 guard let analytics else { return nil }
135- guard let groupId = args. typed ( as: String . self, index: 0 ) else { return nil }
187+ guard let groupId = args. typed ( as: String . self, index: 0 ) else {
188+ return nil
189+ }
136190 let traits = args. typed ( as: Dictionary . self, index: 1 )
137- analytics. group ( groupId: groupId, traits: traits, enrichments: [ originMarkerEnrichment] )
138- return nil
139- }
140-
141- public func alias( args: [ JSConvertible ? ] ) -> JSConvertible ? {
142- guard let analytics else { return nil }
143- guard let newId = args. typed ( as: String . self, index: 0 ) else { return nil }
144- analytics. alias ( newId: newId, enrichments: [ originMarkerEnrichment] )
191+ let context = args. typed ( as: Dictionary . self, index: 2 )
192+ analytics
193+ . group (
194+ groupId: groupId,
195+ traits: traits,
196+ enrichments: enrichments ( with: context)
197+ )
145198 return nil
199+
146200 }
147201
148202 public func flush( args: [ JSConvertible ? ] ) -> JSConvertible ? {
149203 guard let analytics else { return nil }
150204 analytics. flush ( )
151205 return nil
206+
152207 }
153208
154209 public func reset( args: [ JSConvertible ? ] ) -> JSConvertible ? {
155210 guard let analytics else { return nil }
156211 analytics. reset ( )
157212 return nil
213+
158214 }
159215
160216 public func add( args: [ JSConvertible ? ] ) -> JSConvertible ? {
161- var result = false
162-
163- guard let analytics else { return result }
164- guard let plugin = args . typed ( as : JSClass . self , index : 0 ) else { return result }
217+ guard let analytics else { return nil }
218+ guard let plugin = args . typed ( as : JSClass . self , index : 0 ) else {
219+ return false
220+ }
165221
166222 let type = plugin [ " type " ] ? . typed ( as: Int . self)
167223 let destination = plugin [ " destination " ] ? . typed ( as: String . self)
168224
169- guard let type = type else { return result }
225+ guard let type = type else { return false }
226+ guard let pluginType = PluginType ( rawValue: type) else { return false }
170227
171- guard let pluginType = PluginType ( rawValue: type) else { return result }
172228 let edgeFn = LivePlugin ( jsPlugin: plugin, type: pluginType)
173229
174230 if let dest = destination {
175231 // we have a destination specified, so add it there
176- if let d = analytics. find ( key: dest) {
177- DispatchQueue . main. async {
178- _ = d. add ( plugin: edgeFn)
179- }
180- result = true
181- self . addedPlugins. append ( ( dest, edgeFn) )
182- }
232+ guard let d = analytics. find ( key: dest) else { return false }
233+ _ = d. add ( plugin: edgeFn)
234+ return true
183235 } else {
184- DispatchQueue . main. async {
185- _ = analytics. add ( plugin: edgeFn)
186- }
187- result = true
188- self . addedPlugins. append ( ( nil , edgeFn) )
236+ _ = analytics. add ( plugin: edgeFn)
237+ return true
189238 }
190- return result
191- }
192-
193- public func removeLivePlugins( args: [ JSConvertible ? ] ) -> JSConvertible ? {
194- guard let analytics else { return nil }
195-
196- for tuple in self . addedPlugins {
197- let ( dest, p) = tuple
198- if let dst = dest {
199- // Remove from destination
200- if let d = analytics. find ( key: dst) {
201- d. remove ( plugin: p)
202- }
203- } else {
204- // Remove from main timeline
205- analytics. remove ( plugin: p)
206- }
207- }
208- self . addedPlugins. removeAll ( )
209- return nil
210239 }
211240}
0 commit comments