vibes-react-native 5.0.0 → 5.0.1-rc2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/ios/Vibes.swift +2 -3
  2. package/ios/VibesClient.swift +3 -4
  3. package/ios/VibesPluginLogger.swift +2 -5
  4. package/package.json +3 -2
  5. package/vendor/VibesPush/LICENSE +13 -0
  6. package/vendor/VibesPush/Sources/APIDefinition.swift +502 -0
  7. package/vendor/VibesPush/Sources/Actions.swift +24 -0
  8. package/vendor/VibesPush/Sources/AppObserver.swift +137 -0
  9. package/vendor/VibesPush/Sources/AuthTokenBehavior.swift +17 -0
  10. package/vendor/VibesPush/Sources/CombinedLogger.swift +53 -0
  11. package/vendor/VibesPush/Sources/ConsoleLogger.swift +97 -0
  12. package/vendor/VibesPush/Sources/Credential.swift +41 -0
  13. package/vendor/VibesPush/Sources/CredentialManager.swift +24 -0
  14. package/vendor/VibesPush/Sources/Date+iso8601.swift +34 -0
  15. package/vendor/VibesPush/Sources/Date+logPrefix.swift +20 -0
  16. package/vendor/VibesPush/Sources/DeviceToken.swift +15 -0
  17. package/vendor/VibesPush/Sources/DeviceType.swift +143 -0
  18. package/vendor/VibesPush/Sources/Dictionary+merged.swift +11 -0
  19. package/vendor/VibesPush/Sources/Event.swift +83 -0
  20. package/vendor/VibesPush/Sources/EventCollection.swift +36 -0
  21. package/vendor/VibesPush/Sources/EventTracker.swift +39 -0
  22. package/vendor/VibesPush/Sources/FoundationExtensions.swift +16 -0
  23. package/vendor/VibesPush/Sources/GitTag.swift +27 -0
  24. package/vendor/VibesPush/Sources/HTTP/HTTPBehavior.swift +19 -0
  25. package/vendor/VibesPush/Sources/HTTP/HTTPMethod.swift +20 -0
  26. package/vendor/VibesPush/Sources/HTTP/HTTPResource.swift +69 -0
  27. package/vendor/VibesPush/Sources/HTTP/HTTPResourceClient.swift +190 -0
  28. package/vendor/VibesPush/Sources/HTTP/JSONParser.swift +91 -0
  29. package/vendor/VibesPush/Sources/HTTP/Operations/AssociatePersonOperation.swift +56 -0
  30. package/vendor/VibesPush/Sources/HTTP/Operations/BaseOperation.swift +153 -0
  31. package/vendor/VibesPush/Sources/HTTP/Operations/EventOperation.swift +73 -0
  32. package/vendor/VibesPush/Sources/HTTP/Operations/GetGitTagsOperation.swift +61 -0
  33. package/vendor/VibesPush/Sources/HTTP/Operations/GetInboxMessageOperation.swift +59 -0
  34. package/vendor/VibesPush/Sources/HTTP/Operations/GetInboxMessagesOperation.swift +57 -0
  35. package/vendor/VibesPush/Sources/HTTP/Operations/GetPersonOperation.swift +53 -0
  36. package/vendor/VibesPush/Sources/HTTP/Operations/GetVibesAppInfoOperation.swift +45 -0
  37. package/vendor/VibesPush/Sources/HTTP/Operations/MigrationCallbackOperation.swift +45 -0
  38. package/vendor/VibesPush/Sources/HTTP/Operations/RegisterDeviceOperation.swift +66 -0
  39. package/vendor/VibesPush/Sources/HTTP/Operations/RegisterPushOperation.swift +73 -0
  40. package/vendor/VibesPush/Sources/HTTP/Operations/TrackProductActionOperation.swift +75 -0
  41. package/vendor/VibesPush/Sources/HTTP/Operations/TrackPurchaseActionOperation.swift +81 -0
  42. package/vendor/VibesPush/Sources/HTTP/Operations/UnregisterDeviceOperation.swift +64 -0
  43. package/vendor/VibesPush/Sources/HTTP/Operations/UnregisterPushOperation.swift +72 -0
  44. package/vendor/VibesPush/Sources/HTTP/Operations/UpdateDeviceOperationPatch.swift +57 -0
  45. package/vendor/VibesPush/Sources/HTTP/Operations/UpdateDeviceOperationPut.swift +59 -0
  46. package/vendor/VibesPush/Sources/HTTP/Operations/UpdateMessageOperation.swift +50 -0
  47. package/vendor/VibesPush/Sources/HTTP/Operations/VibesQueueOperation.swift +76 -0
  48. package/vendor/VibesPush/Sources/HTTP/ResourceResult.swift +38 -0
  49. package/vendor/VibesPush/Sources/HTTPURLResponse+cURL.swift +16 -0
  50. package/vendor/VibesPush/Sources/InboxMessage.swift +219 -0
  51. package/vendor/VibesPush/Sources/Info.plist +26 -0
  52. package/vendor/VibesPush/Sources/InputStream+readToString.swift +19 -0
  53. package/vendor/VibesPush/Sources/KeychainStorage.swift +64 -0
  54. package/vendor/VibesPush/Sources/LocalObject.swift +25 -0
  55. package/vendor/VibesPush/Sources/LocalStorageKeys.swift +19 -0
  56. package/vendor/VibesPush/Sources/LocalStorageType.swift +47 -0
  57. package/vendor/VibesPush/Sources/LocalValue.swift +67 -0
  58. package/vendor/VibesPush/Sources/PersistentEventStorage.swift +81 -0
  59. package/vendor/VibesPush/Sources/Person.swift +98 -0
  60. package/vendor/VibesPush/Sources/Product.swift +103 -0
  61. package/vendor/VibesPush/Sources/Purchase.swift +108 -0
  62. package/vendor/VibesPush/Sources/TrackedEventType.swift +48 -0
  63. package/vendor/VibesPush/Sources/URLRequest+cURL.swift +36 -0
  64. package/vendor/VibesPush/Sources/UserDefaultsStorage.swift +32 -0
  65. package/vendor/VibesPush/Sources/Vibes.swift +1069 -0
  66. package/vendor/VibesPush/Sources/VibesAPI.swift +81 -0
  67. package/vendor/VibesPush/Sources/VibesAPIDelegate.swift +41 -0
  68. package/vendor/VibesPush/Sources/VibesAppInfo.swift +77 -0
  69. package/vendor/VibesPush/Sources/VibesConfiguration.swift +108 -0
  70. package/vendor/VibesPush/Sources/VibesLogger.swift +65 -0
  71. package/vendor/VibesPush/Sources/VibesResult.swift +78 -0
  72. package/vibes-react-native.podspec +6 -2
@@ -0,0 +1,36 @@
1
+ /// A simple object to encapsulate the notion of an array of Events.
2
+ final class EventCollection {
3
+ /// The events in the collection
4
+ var events: [Event] = []
5
+
6
+ /// Initialize this object.
7
+ ///
8
+ /// - parameters:
9
+ /// - events: the initial events to contain
10
+ init(events: [Event] = []) {
11
+ self.events = events
12
+ }
13
+ }
14
+
15
+ // Ideally, instead of `EventCollection` we would use conditional conformance
16
+ // to do:
17
+ //
18
+ // extension Array: LocalObjectType where Element: LocalObjectType {
19
+ // ...
20
+ // }
21
+ //
22
+ // but this sort of functionality isn't available yet in Swift.
23
+ // See: https://github.com/apple/swift-evolution/blob/master/proposals/0143-conditional-conformances.md
24
+
25
+ extension EventCollection: LocalObjectType {
26
+ var attributes: [String: Any] {
27
+ return ["object": events.map { $0.attributes }]
28
+ }
29
+
30
+ convenience init?(attributes: [String: Any]) {
31
+ self.init()
32
+
33
+ guard let eventAttributes = attributes["object"] as? [[String: Any]] else { return nil }
34
+ self.events = eventAttributes.compactMap { Event(attributes: $0) }
35
+ }
36
+ }
@@ -0,0 +1,39 @@
1
+ /// A protocol for Types that wish to track events.
2
+ protocol EventTracker: class {
3
+ /// Tracks events.
4
+ ///
5
+ /// - parameters:
6
+ /// - events: the Events to track, e.g. [.launch]
7
+ /// - completion: a handler for receiving the result of tracking the events
8
+ /// (it returns an Array of the events that have been tracked)
9
+ func track(events incomingEvents: [Event], completion: VibesCompletion<[Event]>?)
10
+ }
11
+
12
+ extension EventTracker {
13
+ /// A convenience method for tracking a single event.
14
+ ///
15
+ /// - parameters:
16
+ /// - event: the Event to track, e.g. .launch
17
+ /// - completion: a handler for receiving the result of tracking the events
18
+ /// (it returns an Array of the events that have been tracked)
19
+ func track(event incomingEvent: Event, completion: VibesCompletion<[Event]>?) {
20
+ track(events: [incomingEvent], completion: completion)
21
+ }
22
+
23
+ /// A convenience method for tracking events without caring about completion.
24
+ ///
25
+ /// - parameters:
26
+ /// - events: the Events to track, e.g. [.launch]
27
+ func track(events incomingEvents: [Event]) {
28
+ track(events: incomingEvents, completion: nil)
29
+ }
30
+
31
+ /// A convenience method for tracking a single event without caring about
32
+ /// completion.
33
+ ///
34
+ /// - parameters:
35
+ /// - event: the Event to track, e.g. .launch
36
+ func track(event incomingEvent: Event) {
37
+ track(events: [incomingEvent], completion: nil)
38
+ }
39
+ }
@@ -0,0 +1,16 @@
1
+ //
2
+ // FoundationExtensions.swift
3
+ // VibesPush
4
+ //
5
+ // Created by Moin' Victor on 10/08/2021.
6
+ // Copyright © 2021 Vibes. All rights reserved.
7
+ //
8
+
9
+ import Foundation
10
+
11
+ extension String {
12
+ func toJSON() -> Any? {
13
+ guard let data = self.data(using: .utf8, allowLossyConversion: false) else { return nil }
14
+ return try? JSONSerialization.jsonObject(with: data, options: .mutableContainers)
15
+ }
16
+ }
@@ -0,0 +1,27 @@
1
+ //
2
+ // GitTag.swift
3
+ // VibesPush
4
+ //
5
+ // Created by Moin' Victor on 15/09/2020.
6
+ // Copyright © 2020 Vibes. All rights reserved.
7
+ //
8
+
9
+ import Foundation
10
+
11
+ /// A small data object to hold a Git Tag
12
+ public struct GitTag {
13
+ let name: String
14
+ }
15
+
16
+ extension GitTag: JSONEncodable, JSONDecodable {
17
+ init?(json: VibesJSONDictionary) {
18
+ guard let name = json["name"] as? String else { return nil }
19
+ self.name = name
20
+ }
21
+
22
+ func encodeJSON() -> VibesJSONDictionary {
23
+ return [
24
+ "name": name as AnyObject,
25
+ ]
26
+ }
27
+ }
@@ -0,0 +1,19 @@
1
+ import Foundation
2
+ /// A protocol to allow a network client to add behavior around requesting an
3
+ /// HTTP resource.
4
+ ///
5
+ /// This protocol may house more methods in the future, to allow for further
6
+ /// customization of request-handling in a network client (e.g. for before/after
7
+ /// callbacks to support an observer pattern).
8
+ protocol HTTPBehavior {
9
+ /// Allows for the modification of a request object prior to it being sent.
10
+ ///
11
+ /// - parameters:
12
+ /// - request: the request you would like to modify
13
+ func modifyRequest(request: inout URLRequest)
14
+ }
15
+
16
+ // We extend HTTPBehavior with a default no-op for its protocol methods.
17
+ extension HTTPBehavior {
18
+ func modifyRequest(request: inout URLRequest) {}
19
+ }
@@ -0,0 +1,20 @@
1
+ /// A simple enum to provide type safety around HTTP methods.
2
+ enum HTTPMethod: String {
3
+ /// A HEAD method for an HTTP Request.
4
+ case HEAD
5
+
6
+ /// A GET method for an HTTP Request.
7
+ case GET
8
+
9
+ /// A POST method for an HTTP Request.
10
+ case POST
11
+
12
+ /// A PUT method for an HTTP Request.
13
+ case PUT
14
+
15
+ /// A DELETE method for an HTTP Request.
16
+ case DELETE
17
+
18
+ /// A PATCH method for an HTTP Request.
19
+ case PATCH
20
+ }
@@ -0,0 +1,69 @@
1
+ import Foundation
2
+
3
+ /// A generic value object representing an HTTP resource that can be requested
4
+ /// and parsed.
5
+ ///
6
+ /// T represents the Type that will be returned for this resource, e.g.
7
+ /// `Credential` or `String`.
8
+ struct HTTPResource<T> {
9
+ // The base URL to be used for this resource
10
+ var baseURL: URL?
11
+ /// The path of the resource relative to the base url, e.g. "/devices"
12
+ let path: String
13
+
14
+ /// The HTTP method to use to fetch this resource, e.g. .POST
15
+ let method: HTTPMethod
16
+
17
+ /// The body to send when requesting this resource.
18
+ let requestBody: Data?
19
+
20
+ /// A set of headers to send when requesting this resource.
21
+ let headers: [String: String]
22
+
23
+ /// A closure to use to transform the returned Data for the resource into
24
+ /// the generic type, T.
25
+ let parse: (Data) -> T?
26
+
27
+ /// Initialize this object.
28
+ ///
29
+ /// - parameters:
30
+ /// - baseURL: The Base URL, if this is specified, the default base URL will not be used.
31
+ /// - path: The path of the resource relative to the base url, e.g.
32
+ /// "/devices"
33
+ /// - method: The HTTP method to use to fetch this resource, e.g. .POST
34
+ /// - requestBody: The body to send when requesting this resource.
35
+ /// - headers: A set of headers to send when requesting this resource.
36
+ /// - parse: A closure to use to transform the returned Data for the
37
+ /// resource into the generic type, T.
38
+ // swiftlint:disable:next line_length
39
+ init(baseURL: URL? = nil, path: String, method: HTTPMethod = .GET, requestBody: Data? = nil, headers: [String: String] = [:], parse: @escaping (Data) -> T?) {
40
+ self.baseURL = baseURL
41
+ self.path = path
42
+ self.method = method
43
+ self.requestBody = requestBody
44
+ self.headers = headers
45
+ self.parse = parse
46
+ }
47
+
48
+ /// Creates a new URLRequest for this resource. This can be passed to
49
+ /// URLSession to make a network request.
50
+ ///
51
+ /// - parameters:
52
+ /// - baseURL: The base URL to use for a request for this resource, e.g.
53
+ /// "http://example.com". The path will be appended to this.
54
+ func toRequest(baseURL: URL) -> URLRequest {
55
+ // use the base URL provided in the resource or use the default base URL
56
+ let url = (self.baseURL ?? baseURL).appendingPathComponent(path)
57
+ var request = URLRequest(url: url)
58
+
59
+ for (key, value) in headers {
60
+ request.setValue(value, forHTTPHeaderField: key)
61
+ }
62
+ request.httpMethod = method.rawValue
63
+ if method != .GET {
64
+ request.httpBody = requestBody
65
+ }
66
+
67
+ return request
68
+ }
69
+ }
@@ -0,0 +1,190 @@
1
+ import Foundation
2
+ /// A closure used as a completion handler for HTTP requests.
3
+ typealias HTTPCompletion<T> = (ResourceResult<T>) -> Void
4
+
5
+ /// A protocol that indicates the required interface for being considered an
6
+ /// `HTTPResourceClient`
7
+ protocol HTTPResourceClientType {
8
+ func request<A>(resource: HTTPResource<A>,
9
+ behavior: HTTPBehavior?,
10
+ completion: HTTPCompletion<A>?)
11
+ func request<A>(resource: HTTPResource<A>,
12
+ completion: HTTPCompletion<A>?)
13
+ }
14
+
15
+ /// A closure used as a completion handler for URLSessionDataTasks.
16
+ typealias DataTaskResult = (Data?, URLResponse?, Error?) -> Void
17
+
18
+ /// A protocol that indicates the required interface for being considered a
19
+ /// `URLSession` for use with an `HTTPResourceClient`.
20
+ protocol URLSessionType {
21
+ func dataTask(with request: URLRequest,
22
+ completionHandler: @escaping DataTaskResult) -> URLSessionDataTaskType
23
+ }
24
+
25
+ extension URLSession: URLSessionType {
26
+ func dataTask(with request: URLRequest,
27
+ completionHandler: @escaping DataTaskResult) -> URLSessionDataTaskType {
28
+ let task = dataTask(with: request,
29
+ completionHandler: completionHandler) as URLSessionDataTask
30
+ return task as URLSessionDataTaskType
31
+ }
32
+ }
33
+
34
+ /// A protocol that indicates the required interface for being considered a
35
+ /// `URLSessionDataTask` for use with an `HTTPResourceClient`.
36
+ protocol URLSessionDataTaskType {
37
+ func resume()
38
+ }
39
+
40
+ extension URLSessionDataTask: URLSessionDataTaskType {}
41
+
42
+ extension HTTPResourceClientType {
43
+ /// Make an HTTP request for an `HTTPResource`.
44
+ ///
45
+ /// - parameters:
46
+ /// - resource: The resource to request
47
+ /// - completion: A handler for when the request fails or succeeds.
48
+ func request<A>(resource: HTTPResource<A>,
49
+ completion: HTTPCompletion<A>?) {
50
+ request(resource: resource, behavior: nil, completion: completion)
51
+ }
52
+ }
53
+
54
+ /// A network client that knows how to take `HTTPResource` objects, request them
55
+ /// via URLSession, and parse them.
56
+ class HTTPResourceClient: HTTPResourceClientType {
57
+ /// The base URL to use for this network client, e.g. "http://example.com"
58
+ private let baseURL: URL
59
+
60
+ /// A session to use, usually URLSession.shared.
61
+ private let session: URLSessionType
62
+
63
+ /// Optional provider for request/response logging. Evaluated per request so
64
+ /// it is safe before `Vibes.configure` has finished.
65
+ private let loggerProvider: () -> VibesLogger?
66
+
67
+ /// Initialize this object.
68
+ ///
69
+ /// - parameters:
70
+ /// - baseURL: the base URL to use for this network client, e.g.
71
+ /// "http://example.com"
72
+ /// - session: the `URLSessionType` to use for making HTTP requests
73
+ /// - loggerProvider: returns the logger to use for this request, if any
74
+ init(baseURL: URL,
75
+ session: URLSessionType = URLSession.shared,
76
+ loggerProvider: @escaping () -> VibesLogger? = { nil }) {
77
+ self.baseURL = baseURL
78
+ self.session = session
79
+ self.loggerProvider = loggerProvider
80
+ }
81
+
82
+ /// Make an HTTP request for an `HTTPResource`.
83
+ ///
84
+ /// - parameters:
85
+ /// - resource: The resource to request
86
+ /// - behavior: An optional HTTPBehavior to apply to the request
87
+ /// - completion: A handler for when the request fails or succeeds.
88
+ func request<A>(resource: HTTPResource<A>,
89
+ behavior: HTTPBehavior?,
90
+ completion: HTTPCompletion<A>?) {
91
+ var request = resource.toRequest(baseURL: baseURL)
92
+ behavior?.modifyRequest(request: &request)
93
+
94
+ loggerProvider()?.log(request: request)
95
+
96
+ let task = session.dataTask(with: request) { data, response, error in
97
+ if let error = error {
98
+ self.loggerProvider()?.log(error: error)
99
+ self.handleError(error, completion: completion)
100
+ return
101
+ }
102
+
103
+ if let response = response {
104
+ self.loggerProvider()?.log(response: response, data: data)
105
+ }
106
+
107
+ guard let response = response as? HTTPURLResponse else {
108
+ completion?(.failure(.other(error)))
109
+ return
110
+ }
111
+
112
+ guard 200 ... 299 ~= response.statusCode else {
113
+ self.handleResponseWithStatusCode(of: response.statusCode,
114
+ data: data,
115
+ completion: completion)
116
+ return
117
+ }
118
+
119
+ guard let data = data else {
120
+ completion?(.failure(.noData))
121
+ return
122
+ }
123
+
124
+ if let value = resource.parse(data) {
125
+ completion?(.success(value))
126
+ } else {
127
+ completion?(.failure(.couldNotParse(data: data)))
128
+ }
129
+ }
130
+
131
+ task.resume()
132
+ }
133
+
134
+ /// Handle an error in even being able to make a request.
135
+ ///
136
+ /// - parameters:
137
+ /// - error: The error
138
+ /// - completion: A handler for when the request fails or succeeds.
139
+ fileprivate func handleError<A>(_ error: Error?, completion: HTTPCompletion<A>?) {
140
+ if let nserror = error as NSError? {
141
+ switch nserror.code {
142
+ case NSURLErrorTimedOut, NSURLErrorNotConnectedToInternet: completion?(.failure(.unreachable))
143
+ default: completion?(.failure(.other(error)))
144
+ }
145
+ }
146
+ }
147
+
148
+ /// Handle an HTTP response status (which may indicate an error or a success).
149
+ ///
150
+ /// - parameters:
151
+ /// - statusCode: The HTTP response code, e.g. 200 or 502
152
+ /// - data: The data returned with the response
153
+ /// - completion: A handler for when the request fails or succeeds.
154
+ fileprivate func handleResponseWithStatusCode<A>(of statusCode: Int,
155
+ data: Data?,
156
+ completion: HTTPCompletion<A>?) {
157
+ let responseText = String(data: data ?? Data(), encoding: .utf8)
158
+
159
+ switch statusCode {
160
+ case 401: completion?(.failure(.unauthorized))
161
+ default:
162
+ let error = ResourceError.invalidResponse(statusCode: statusCode, responseText: responseText ?? "")
163
+ completion?(.failure(error))
164
+ }
165
+ }
166
+ }
167
+
168
+ internal extension URLRequest {
169
+
170
+ func toString() -> String {
171
+ return """
172
+ \(httpMethod!) \((url?.absoluteString)!),
173
+ \nBody: \(String(describing: httpBody != nil ? String(data: httpBody!,
174
+ encoding: String.Encoding.utf8)! : "")) \nHeaders: \(allHTTPHeaderFields!)
175
+ """
176
+ }
177
+ }
178
+
179
+ internal extension Int {
180
+
181
+ /// Returns `true` if this Int is a status code value to be retried
182
+ func isStatusCodeForRetryableServerError() -> Bool {
183
+ switch self {
184
+ case 408, 429, 500, 502, 503, 504:
185
+ return true
186
+ default:
187
+ return false
188
+ }
189
+ }
190
+ }
@@ -0,0 +1,91 @@
1
+ import Foundation
2
+
3
+ /// A Type for a JSON dictionary (object)
4
+ public typealias VibesJSONDictionary = [String: AnyObject]
5
+ /// A Type for Vibes Tracking JSON dictionary (object)
6
+ public typealias VibesTrackingData = [String: Any]
7
+ /// A Type for a JSON array
8
+ typealias VibesJSONArray = [VibesJSONDictionary]
9
+
10
+ /// A protocol that can be adopted to say that a Type can be encoded into JSON.
11
+ protocol JSONEncodable {
12
+ /// Encodes this Type into a JSONDictionary.
13
+ func encodeJSON() -> VibesJSONDictionary
14
+ }
15
+
16
+ /// A protocol that can be adopted to say that a Type can be decoded from JSON.
17
+ protocol JSONDecodable {
18
+ /// A convenience initializer for decoding a JSONDictionary into this Type.
19
+ ///
20
+ /// - parameters:
21
+ /// - json: the JSONDictionary to encode into data
22
+ init?(json: VibesJSONDictionary)
23
+ }
24
+
25
+ /// Allows the ability to decode/encode `Data` to/from a `JSONDictionary`.
26
+ struct JSONParser {
27
+ /// Decodes data into a JSONDictionary.
28
+ ///
29
+ /// - parameters:
30
+ /// - data: the data to decode
31
+ func decode(data: Data) -> VibesJSONDictionary? {
32
+ // Treat an existing but blank data as an empty JSON object
33
+ guard !data.isEmpty else { return [:] }
34
+
35
+ // swiftlint:disable:next force_cast
36
+ return try? JSONSerialization.jsonObject(with: data) as? VibesJSONDictionary
37
+ }
38
+
39
+ /// Decodes data into a JSONArray.
40
+ ///
41
+ /// - parameters:
42
+ /// - data: the data to decode
43
+ func decodeJSONArray(data: Data) -> VibesJSONArray? {
44
+ // Treat an existing but blank data as an empty JSON object
45
+ guard !data.isEmpty else { return [] }
46
+
47
+ guard let arrayJson = ((try? JSONSerialization.jsonObject(with: data) as? VibesJSONArray) as VibesJSONArray??)
48
+ else {
49
+ return nil
50
+ }
51
+
52
+ return arrayJson
53
+ }
54
+
55
+ /// Encodes a JSONEncodable to data.
56
+ ///
57
+ /// - parameters:
58
+ /// - object: a JSONEncodable object to encode into data
59
+ func encode(_ object: JSONEncodable) -> Data? {
60
+ let dict = object.encodeJSON()
61
+ return encode(dict)
62
+ }
63
+
64
+ /// Encodes an array of JSONEncodable objects to data.
65
+ ///
66
+ /// - parameters:
67
+ /// - objects: an array of JSONEncodable object to encode into data
68
+ func encode(_ objects: [JSONEncodable]) -> Data? {
69
+ let array = objects.map { $0.encodeJSON() }
70
+ return encode(array)
71
+ }
72
+
73
+ /// Encodes a JSONDictionary to data.
74
+ ///
75
+ /// - parameters:
76
+ /// - dict: the JSONDictionary to encode into data
77
+ func encode(_ dict: VibesJSONDictionary) -> Data? {
78
+ guard !dict.isEmpty else { return nil }
79
+ guard JSONSerialization.isValidJSONObject(dict) else { return nil }
80
+ return try? JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted)
81
+ }
82
+
83
+ /// Encodes a JSONArray to data.
84
+ ///
85
+ /// - parameters:
86
+ /// - array: the JSONArray to encode into data
87
+ func encode(_ array: VibesJSONArray) -> Data? {
88
+ guard JSONSerialization.isValidJSONObject(array) else { return nil }
89
+ return try? JSONSerialization.data(withJSONObject: array, options: .prettyPrinted)
90
+ }
91
+ }
@@ -0,0 +1,56 @@
1
+ //
2
+ // AssociatePersonOperation.swift
3
+ // VibesPush-iOS
4
+ //
5
+ // Created by Peter Compernolle on 5/30/2018.
6
+ // Copyright © 2018 Vibes. All rights reserved.
7
+ //
8
+
9
+ internal class AssociatePersonOperation: BaseOperation<Void> {
10
+ fileprivate let resource: () -> HTTPResource<Void>
11
+ fileprivate weak var delegate: VibesAPIDelegate?
12
+ fileprivate var callback: VibesCompletion<Void>?
13
+
14
+ /// Completion handler responsible for notifying sdk users
15
+ fileprivate lazy var completionHandler: VibesCompletion<Void> = {[weak self] (result) in
16
+ switch result {
17
+ case .success:
18
+ self?.callback?(.success(()))
19
+ self?.delegate?.didAssociatePerson?(error: nil)
20
+ case .failure(let error):
21
+ self?.callback?(.failure(error))
22
+ self?.delegate?.didAssociatePerson?(error: error)
23
+ }
24
+ }
25
+
26
+ /// Initialize this object
27
+ ///
28
+ /// - parameters:
29
+ /// - credentialManager: an object to store credentials, keeping track of the current Credential..
30
+ /// - api: an object that allows talking to the Vibes API
31
+ /// - advertisingId: AdSupport.advertisingId
32
+ /// - appId: the application ID provided by Vibes to identify this application
33
+ /// - delegate: VibesAPIDelegate.
34
+ /// - externalPersonId: a String representation of the third party person identifier
35
+ public init(credentials: CredentialManager,
36
+ api: VibesAPIType,
37
+ advertisingId: String,
38
+ appId: String,
39
+ delegate: VibesAPIDelegate?,
40
+ callback: VibesCompletion<Void>? = nil,
41
+ externalPersonId: String) {
42
+ self.delegate = delegate
43
+ self.callback = callback
44
+ resource = {
45
+ let deviceId = credentials.currentCredential?.deviceId ?? VibesQueueConstant.NONE
46
+ return APIDefinition.associatePerson(appId: appId, deviceId: deviceId, externalPersonId: externalPersonId)
47
+ }
48
+ super.init(credentials: credentials, api: api, advertisingId: advertisingId, appId: appId)
49
+ }
50
+
51
+ /// Execute the operation
52
+ override func start() {
53
+ super.start()
54
+ super.execute(retry: 0, resource: resource, completion: completionHandler)
55
+ }
56
+ }