react-native-sdk-pianoio 0.3.1 → 0.3.4

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 (37) hide show
  1. package/README.md +176 -186
  2. package/android/build.gradle +29 -42
  3. package/android/gradle.properties +33 -14
  4. package/android/src/main/java/com/sdkpianoio/ComposerPianoImpl.kt +366 -0
  5. package/android/src/main/java/com/sdkpianoio/SdkPianoioModule.kt +281 -507
  6. package/android/src/main/java/com/sdkpianoio/TokenService.kt +139 -0
  7. package/android/test.sh +494 -0
  8. package/ios/ComposerPianoImpl.swift +128 -225
  9. package/ios/MyComposerDelegate.swift +142 -109
  10. package/ios/SdkPianoio.swift +69 -143
  11. package/ios/SdkPianoioBridge.m +18 -46
  12. package/ios/TokenService.swift +219 -0
  13. package/lib/commonjs/NativeSdkPianoio.ts +35 -22
  14. package/lib/commonjs/PianoComposer.js +89 -132
  15. package/lib/commonjs/PianoComposer.js.map +1 -1
  16. package/lib/commonjs/index.js.map +1 -1
  17. package/lib/module/NativeSdkPianoio.ts +35 -22
  18. package/lib/module/PianoComposer.js +90 -132
  19. package/lib/module/PianoComposer.js.map +1 -1
  20. package/lib/module/index.js +0 -14
  21. package/lib/module/index.js.map +1 -1
  22. package/lib/typescript/commonjs/src/NativeSdkPianoio.d.ts +28 -21
  23. package/lib/typescript/commonjs/src/NativeSdkPianoio.d.ts.map +1 -1
  24. package/lib/typescript/commonjs/src/PianoComposer.d.ts +55 -31
  25. package/lib/typescript/commonjs/src/PianoComposer.d.ts.map +1 -1
  26. package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
  27. package/lib/typescript/module/src/NativeSdkPianoio.d.ts +28 -21
  28. package/lib/typescript/module/src/NativeSdkPianoio.d.ts.map +1 -1
  29. package/lib/typescript/module/src/PianoComposer.d.ts +55 -31
  30. package/lib/typescript/module/src/PianoComposer.d.ts.map +1 -1
  31. package/lib/typescript/module/src/index.d.ts.map +1 -1
  32. package/package.json +5 -2
  33. package/src/NativeSdkPianoio.ts +35 -22
  34. package/src/PianoComposer.tsx +78 -141
  35. package/src/index.tsx +0 -14
  36. package/android/src/main/AndroidManifestNew.xml +0 -2
  37. package/ios/services/TokenService.swift +0 -70
@@ -1,150 +1,76 @@
1
1
  import Foundation
2
2
  import React
3
- import PianoComposer
4
- import PianoOAuth
5
3
 
4
+ /**
5
+ * SdkPianoio - The main React Native bridge module for the Piano SDK.
6
+ *
7
+ * This class exposes the functionality of the ComposerPianoImpl to JavaScript.
8
+ */
6
9
  @objc(SdkPianoio)
7
10
  class SdkPianoio: NSObject {
8
- private var moduleImpl: ComposerPianoImpl?
9
-
10
- override init() {
11
- super.init()
12
- self.moduleImpl = ComposerPianoImpl()
13
- }
14
-
15
- @objc
16
- static func requiresMainQueueSetup() -> Bool {
17
- return false
18
- }
19
-
20
- @objc(initializeComposer:resolver:rejecter:)
21
- func initializeComposer(aid: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
22
- moduleImpl?.initializeComposer(aid)
23
- resolver(true)
24
- }
25
-
26
- @objc(getComposer:rejecter:)
27
- func getComposer(resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
28
- guard let moduleImpl = moduleImpl else {
29
- rejecter("composer_error", "Composer not initialized", nil)
30
- return
11
+
12
+ // The single, persistent instance of our implementation class.
13
+ private var moduleImpl: ComposerPianoImpl?
14
+
15
+ override init() {
16
+ self.moduleImpl = ComposerPianoImpl()
17
+ super.init()
18
+ }
19
+
20
+ @objc(initialize:resolver:rejecter:)
21
+ func initialize(aid: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
22
+ moduleImpl?.initialize(aid: aid)
23
+ resolver(true)
24
+ }
25
+
26
+ // MARK: - Configuration Methods
27
+
28
+ @objc(addTag:resolver:rejecter:)
29
+ func addTag(tag: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
30
+ moduleImpl?.addTag(tag)
31
+ resolver(true)
32
+ }
33
+
34
+ @objc(addTags:resolver:rejecter:)
35
+ func addTags(tags: [String], resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
36
+ moduleImpl?.addTags(tags)
37
+ resolver(true)
38
+ }
39
+
40
+ @objc(setZoneId:resolver:rejecter:)
41
+ func setZoneId(zoneId: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
42
+ moduleImpl?.setZoneId(zoneId)
43
+ resolver(true)
31
44
  }
32
-
33
- let composer = moduleImpl.getComposer()
34
- if composer != nil {
35
- let response: [String: Any] = [
36
- "aid": moduleImpl.getAid(),
37
- "tags": moduleImpl.getTags(),
38
- "zoneId": moduleImpl.getZoneId(),
39
- "referrer": moduleImpl.getReferrer(),
40
- "url": moduleImpl.getUrl(),
41
- "userToken": moduleImpl.getUserToken()
42
- ]
43
- resolver(response)
44
- } else {
45
- rejecter("composer_error", "Cannot get composer", nil)
45
+
46
+ @objc(setReferrer:resolver:rejecter:)
47
+ func setReferrer(referrer: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
48
+ moduleImpl?.setReferrer(referrer)
49
+ resolver(true)
50
+ }
51
+
52
+ @objc(setUrl:resolver:rejecter:)
53
+ func setUrl(url: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
54
+ moduleImpl?.setUrl(url)
55
+ resolver(true)
56
+ }
57
+
58
+ @objc(setUserToken:resolver:rejecter:)
59
+ func setUserToken(token: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
60
+ moduleImpl?.setUserToken(token)
61
+ resolver(true)
62
+ }
63
+
64
+ @objc(setCustomVariable:value:resolver:rejecter:)
65
+ func setCustomVariable(name: String, value: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
66
+ moduleImpl?.setCustomVariable(name, value: value)
67
+ resolver(true)
68
+ }
69
+
70
+ // MARK: - Execution Method
71
+
72
+ @objc(executeExperience:rejecter:)
73
+ func executeExperience(resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
74
+ moduleImpl?.executeExperience(resolver: resolver, rejecter: rejecter)
46
75
  }
47
- }
48
-
49
- @objc(addComposerTag:resolver:rejecter:)
50
- func addComposerTag(tag: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
51
- moduleImpl?.addTag(tag)
52
- resolver(nil)
53
- }
54
-
55
- @objc(addComposerTags:resolver:rejecter:)
56
- func addComposerTags(tags: [String], resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
57
- moduleImpl?.addTags(tags)
58
- resolver(nil)
59
- }
60
-
61
- @objc(setComposerCustomVariable:value:resolver:rejecter:)
62
- func setComposerCustomVariable(name: String, value: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
63
- moduleImpl?.setCustomVariable(name, value: value)
64
- resolver(nil)
65
- }
66
-
67
- @objc(setComposerReferrer:resolver:rejecter:)
68
- func setComposerReferrer(referrer: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
69
- moduleImpl?.setReferrer(referrer)
70
- resolver(nil)
71
- }
72
-
73
- @objc(setComposerUrl:resolver:rejecter:)
74
- func setComposerUrl(url: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
75
- moduleImpl?.setUrl(url)
76
- resolver(nil)
77
- }
78
-
79
- @objc(setComposerUserToken:resolver:rejecter:)
80
- func setComposerUserToken(token: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
81
- moduleImpl?.setUserToken(token)
82
- resolver(nil)
83
- }
84
-
85
- @objc(setComposerZoneId:resolver:rejecter:)
86
- func setComposerZoneId(zoneId: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
87
- moduleImpl?.setZoneId(zoneId)
88
- resolver(nil)
89
- }
90
-
91
- @objc(executeExperience:rejecter:)
92
- func executeExperience(resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
93
- moduleImpl?.executeExperience(resolver: resolver, rejecter: rejecter)
94
- }
95
-
96
- @objc(executeComposer:rejecter:)
97
- func executeComposer(resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
98
- moduleImpl?.executeComposerWithResolver(resolver: resolver, rejecter: rejecter)
99
- }
100
-
101
- @objc(showLogin:rejecter:)
102
- func showLogin(resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
103
- moduleImpl?.showLoginWithResolver(resolver: resolver, rejecter: rejecter)
104
- }
105
-
106
- @objc(showTemplate:rejecter:)
107
- func showTemplate(resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
108
- moduleImpl?.showTemplateWithResolver(resolver: resolver, rejecter: rejecter)
109
- }
110
-
111
- @objc(showForm:rejecter:)
112
- func showForm(resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
113
- moduleImpl?.showFormWithResolver(resolver: resolver, rejecter: rejecter)
114
- }
115
-
116
- @objc(showRecommendations:rejecter:)
117
- func showRecommendations(resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
118
- moduleImpl?.showRecommendationsWithResolver(resolver: resolver, rejecter: rejecter)
119
- }
120
-
121
- @objc(nonSite:rejecter:)
122
- func nonSite(resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
123
- moduleImpl?.nonSiteWithResolver(resolver: resolver, rejecter: rejecter)
124
- }
125
-
126
- @objc(userSegmentTrue:rejecter:)
127
- func userSegmentTrue(resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
128
- moduleImpl?.userSegmentTrueWithResolver(resolver: resolver, rejecter: rejecter)
129
- }
130
-
131
- @objc(userSegmentFalse:rejecter:)
132
- func userSegmentFalse(resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
133
- moduleImpl?.userSegmentFalseWithResolver(resolver: resolver, rejecter: rejecter)
134
- }
135
-
136
- @objc(meterActive:rejecter:)
137
- func meterActive(resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
138
- moduleImpl?.meterActiveWithResolver(resolver: resolver, rejecter: rejecter)
139
- }
140
-
141
- @objc(meterExpired:rejecter:)
142
- func meterExpired(resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
143
- moduleImpl?.meterExpiredWithResolver(resolver: resolver, rejecter: rejecter)
144
- }
145
-
146
- @objc(composerExecutionCompleted:rejecter:)
147
- func composerExecutionCompleted(resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
148
- moduleImpl?.composerExecutionCompletedWithResolver(resolver: resolver, rejecter: rejecter)
149
- }
150
- }
76
+ }
@@ -1,81 +1,53 @@
1
1
  #import <React/RCTBridgeModule.h>
2
2
 
3
- // Questa macro registra la sua classe Swift 'SdkPianoio' con il bridge di React Native.
3
+ // This macro registers the Swift class 'SdkPianoio' with the React Native bridge.
4
4
  @interface RCT_EXTERN_MODULE(SdkPianoio, NSObject)
5
5
 
6
- // Ora, esponiamo ogni metodo dalla sua classe Swift che vogliamo chiamare da JavaScript.
7
- // Le annotazioni @objc(...) nel suo file Swift definiscono queste esatte firme.
6
+ // MARK: - Initialization
8
7
 
9
- RCT_EXTERN_METHOD(initializeComposer:(NSString *)aid
8
+ RCT_EXTERN_METHOD(initialize:(NSString *)aid
10
9
  resolver:(RCTPromiseResolveBlock)resolve
11
10
  rejecter:(RCTPromiseRejectBlock)reject)
12
11
 
13
- RCT_EXTERN_METHOD(getComposer:(RCTPromiseResolveBlock)resolve
14
- rejecter:(RCTPromiseRejectBlock)reject)
12
+ // MARK: - Configuration Methods
15
13
 
16
- RCT_EXTERN_METHOD(addComposerTag:(NSString *)tag
14
+ RCT_EXTERN_METHOD(addTag:(NSString *)tag
17
15
  resolver:(RCTPromiseResolveBlock)resolve
18
16
  rejecter:(RCTPromiseRejectBlock)reject)
19
17
 
20
- RCT_EXTERN_METHOD(addComposerTags:(NSArray<NSString *> *)tags
18
+ RCT_EXTERN_METHOD(addTags:(NSArray<NSString *> *)tags
21
19
  resolver:(RCTPromiseResolveBlock)resolve
22
20
  rejecter:(RCTPromiseRejectBlock)reject)
23
21
 
24
- RCT_EXTERN_METHOD(setComposerCustomVariable:(NSString *)name
25
- value:(NSString *)value
22
+ RCT_EXTERN_METHOD(setZoneId:(NSString *)zoneId
26
23
  resolver:(RCTPromiseResolveBlock)resolve
27
24
  rejecter:(RCTPromiseRejectBlock)reject)
28
25
 
29
- RCT_EXTERN_METHOD(setComposerReferrer:(NSString *)referrer
26
+ RCT_EXTERN_METHOD(setReferrer:(NSString *)referrer
30
27
  resolver:(RCTPromiseResolveBlock)resolve
31
28
  rejecter:(RCTPromiseRejectBlock)reject)
32
29
 
33
- RCT_EXTERN_METHOD(setComposerUrl:(NSString *)url
30
+ RCT_EXTERN_METHOD(setUrl:(NSString *)url
34
31
  resolver:(RCTPromiseResolveBlock)resolve
35
32
  rejecter:(RCTPromiseRejectBlock)reject)
36
33
 
37
- RCT_EXTERN_METHOD(setComposerUserToken:(NSString *)token
34
+ RCT_EXTERN_METHOD(setUserToken:(NSString *)token
38
35
  resolver:(RCTPromiseResolveBlock)resolve
39
36
  rejecter:(RCTPromiseRejectBlock)reject)
40
37
 
41
- RCT_EXTERN_METHOD(setComposerZoneId:(NSString *)zoneId
38
+ RCT_EXTERN_METHOD(setCustomVariable:(NSString *)name
39
+ value:(NSString *)value
42
40
  resolver:(RCTPromiseResolveBlock)resolve
43
41
  rejecter:(RCTPromiseRejectBlock)reject)
44
42
 
45
- RCT_EXTERN_METHOD(executeExperience:(RCTPromiseResolveBlock)resolve
46
- rejecter:(RCTPromiseRejectBlock)reject)
47
-
48
- RCT_EXTERN_METHOD(executeComposer:(RCTPromiseResolveBlock)resolve
49
- rejecter:(RCTPromiseRejectBlock)reject)
50
-
51
- RCT_EXTERN_METHOD(showLogin:(RCTPromiseResolveBlock)resolve
52
- rejecter:(RCTPromiseRejectBlock)reject)
53
-
54
- RCT_EXTERN_METHOD(showTemplate:(RCTPromiseResolveBlock)resolve
55
- rejecter:(RCTPromiseRejectBlock)reject)
56
-
57
- RCT_EXTERN_METHOD(showForm:(RCTPromiseResolveBlock)resolve
58
- rejecter:(RCTPromiseRejectBlock)reject)
43
+ // MARK: - Execution Method
59
44
 
60
- RCT_EXTERN_METHOD(showRecommendations:(RCTPromiseResolveBlock)resolve
61
- rejecter:(RCTPromiseRejectBlock)reject)
62
-
63
- RCT_EXTERN_METHOD(nonSite:(RCTPromiseResolveBlock)resolve
64
- rejecter:(RCTPromiseRejectBlock)reject)
65
-
66
- RCT_EXTERN_METHOD(userSegmentTrue:(RCTPromiseResolveBlock)resolve
67
- rejecter:(RCTPromiseRejectBlock)reject)
68
-
69
- RCT_EXTERN_METHOD(userSegmentFalse:(RCTPromiseResolveBlock)resolve
70
- rejecter:(RCTPromiseRejectBlock)reject)
71
-
72
- RCT_EXTERN_METHOD(meterActive:(RCTPromiseResolveBlock)resolve
73
- rejecter:(RCTPromiseRejectBlock)reject)
74
-
75
- RCT_EXTERN_METHOD(meterExpired:(RCTPromiseResolveBlock)resolve
45
+ RCT_EXTERN_METHOD(executeExperience:(RCTPromiseResolveBlock)resolve
76
46
  rejecter:(RCTPromiseRejectBlock)reject)
77
47
 
78
- RCT_EXTERN_METHOD(composerExecutionCompleted:(RCTPromiseResolveBlock)resolve
79
- rejecter:(RCTPromiseRejectBlock)reject)
48
+ // Note: Authentication methods (signIn, signOut, etc.) would be added here
49
+ // if they were exposed from SdkPianoio.swift. Since they are handled internally
50
+ // by the Composer/TokenService interaction, they don't need to be exposed directly
51
+ // unless you add them to the SdkPianoio.swift class.
80
52
 
81
53
  @end
@@ -0,0 +1,219 @@
1
+ import PianoOAuth
2
+ import Foundation
3
+
4
+ /**
5
+ * Represents a user from the Piano ID SDK.
6
+ * This custom class simplifies passing user data back to React Native.
7
+ */
8
+ public class User {
9
+ let id: String
10
+ let email: String
11
+ let accessToken: String
12
+
13
+ init(id: String, email: String, accessToken: String) {
14
+ self.id = id
15
+ self.email = email
16
+ self.accessToken = accessToken
17
+ }
18
+ }
19
+
20
+ /**
21
+ * TokenService - Manages OAuth tokens and authentication with the Piano ID SDK.
22
+ *
23
+ * This class is responsible for:
24
+ * - Integrating with the real PianoID SDK.
25
+ * - Managing user authentication (sign-in, sign-out).
26
+ * - Storing and providing the current user's token and information.
27
+ */
28
+ public class TokenService: NSObject, PianoIDDelegate {
29
+
30
+ // MARK: - Properties
31
+
32
+ private var cachedToken: PianoIDToken?
33
+ private var isInitialized: Bool = false
34
+
35
+ // Promises to communicate results of async operations back to React Native
36
+ private var signInResolver: ((Any?) -> Void)?
37
+ private var signInRejecter: ((String?, String?, Error?) -> Void)?
38
+ private var signOutResolver: ((Any?) -> Void)?
39
+ private var signOutRejecter: ((String?, String?, Error?) -> Void)?
40
+
41
+ // MARK: - Initialization
42
+
43
+ /**
44
+ * Initializes the TokenService and configures the PianoID singleton.
45
+ *
46
+ * @param aid The Piano Application ID.
47
+ */
48
+ public func initialize(aid: String) {
49
+ if isInitialized {
50
+ return
51
+ }
52
+ print("TokenService: Initializing with AID: \(aid)")
53
+
54
+ PianoID.shared.aid = aid
55
+ PianoID.shared.endpoint = PianoEndpoint.production
56
+ PianoID.shared.delegate = self
57
+
58
+ isInitialized = true
59
+ print("TokenService: Initialization completed successfully")
60
+ }
61
+
62
+ // MARK: - Authentication Methods
63
+
64
+ /**
65
+ * Starts the sign-in process.
66
+ *
67
+ * @param resolver The promise resolver from React Native.
68
+ * @param rejecter The promise rejecter from React Native.
69
+ */
70
+ public func signIn(resolver: @escaping (Any?) -> Void, rejecter: @escaping (String?, String?, Error?) -> Void) {
71
+ if !isInitialized {
72
+ print("TokenService: Not initialized. Call initialize() first.")
73
+ rejecter("INIT_ERROR", "TokenService not initialized", nil)
74
+ return
75
+ }
76
+ print("TokenService: Starting sign in")
77
+ self.signInResolver = resolver
78
+ self.signInRejecter = rejecter
79
+ PianoID.shared.signIn()
80
+ }
81
+
82
+ /**
83
+ * Starts the sign-out process.
84
+ *
85
+ * @param resolver The promise resolver from React Native.
86
+ * @param rejecter The promise rejecter from React Native.
87
+ */
88
+ public func signOut(resolver: @escaping (Any?) -> Void, rejecter: @escaping (String?, String?, Error?) -> Void) {
89
+ if !isInitialized {
90
+ print("TokenService: Not initialized.")
91
+ rejecter("INIT_ERROR", "TokenService not initialized", nil)
92
+ return
93
+ }
94
+ guard let token = self.cachedToken else {
95
+ print("TokenService: No user is signed in.")
96
+ resolver(["success": true]) // Already signed out
97
+ return
98
+ }
99
+
100
+ print("TokenService: Starting sign out")
101
+ self.signOutResolver = resolver
102
+ self.signOutRejecter = rejecter
103
+ PianoID.shared.signOut(token: token.accessToken)
104
+ }
105
+
106
+ // MARK: - User Information Methods
107
+
108
+ /**
109
+ * Gets the current user's information.
110
+ *
111
+ * @return A User object if authenticated, otherwise null.
112
+ */
113
+ public func getCurrentUser() -> User? {
114
+ guard let token = self.cachedToken else {
115
+ return nil
116
+ }
117
+
118
+ // Decode the JWT to get the claims
119
+ let claims = decode(jwtToken: token.accessToken)
120
+
121
+ // Extract user_id and email from the claims
122
+ let userId = claims?["uid"] as? String ?? "unknown" // Piano ID often uses 'uid' in the JWT
123
+ let email = claims?["email"] as? String ?? "unknown"
124
+
125
+ return User(
126
+ id: userId,
127
+ email: email,
128
+ accessToken: token.accessToken
129
+ )
130
+ }
131
+
132
+ /**
133
+ * Checks if a user is currently authenticated.
134
+ *
135
+ * @return true if a valid token exists, false otherwise.
136
+ */
137
+ public func isAuthenticated() -> Bool {
138
+ return self.cachedToken != nil
139
+ }
140
+
141
+ // MARK: - PianoIDDelegate Implementation
142
+
143
+ public func signIn(result: PianoIDSignInResult!, withError error: Error!) {
144
+ if let r = result {
145
+ print("TokenService: Sign in successful")
146
+ self.cachedToken = r.token
147
+ let user = self.getCurrentUser()
148
+
149
+ let resultMap: [String: Any] = [
150
+ "success": true,
151
+ "userId": user?.id ?? "",
152
+ "userEmail": user?.email ?? "",
153
+ "accessToken": user?.accessToken ?? ""
154
+ ]
155
+ self.signInResolver?(resultMap)
156
+ } else if let e = error {
157
+ print("TokenService: Sign in failed: \(e.localizedDescription)")
158
+ self.signInRejecter?("SIGNIN_ERROR", e.localizedDescription, e)
159
+ }
160
+ // Clean up promises
161
+ self.signInResolver = nil
162
+ self.signInRejecter = nil
163
+ }
164
+
165
+ public func signOut(withError error: Error!) {
166
+ if let e = error {
167
+ print("TokenService: Sign out failed: \(e.localizedDescription)")
168
+ self.signOutRejecter?("SIGNOUT_ERROR", e.localizedDescription, e)
169
+ } else {
170
+ print("TokenService: Sign out successful")
171
+ self.cachedToken = nil
172
+ self.signOutResolver?(["success": true])
173
+ }
174
+ // Clean up promises
175
+ self.signOutResolver = nil
176
+ self.signOutRejecter = nil
177
+ }
178
+
179
+ public func cancel() {
180
+ print("TokenService: User cancelled the flow")
181
+ // If there's an active sign-in promise, reject it.
182
+ if let rejecter = self.signInRejecter {
183
+ rejecter("CANCELLED", "User cancelled the sign-in process.", nil)
184
+ self.signInResolver = nil
185
+ self.signInRejecter = nil
186
+ }
187
+ }
188
+
189
+ // MARK: - Helper Methods
190
+
191
+ /**
192
+ * Decodes the payload of a JWT.
193
+ *
194
+ * @param jwt The JSON Web Token string.
195
+ * @return A dictionary of claims, or nil if decoding fails.
196
+ */
197
+ private func decode(jwtToken jwt: String) -> [String: Any]? {
198
+ let segments = jwt.components(separatedBy: ".")
199
+ guard segments.count > 1 else {
200
+ print("JWT Error: Invalid token format")
201
+ return nil
202
+ }
203
+
204
+ var base64String = segments[1]
205
+ let requiredLength = Int(4 * ceil(Float(base64String.count) / 4.0))
206
+ let nbrPaddings = requiredLength - base64String.count
207
+ if nbrPaddings > 0 {
208
+ let padding = String(repeating: "=", count: nbrPaddings)
209
+ base64String = base64String.appending(padding)
210
+ }
211
+
212
+ guard let data = Data(base64Encoded: base64String, options: .ignoreUnknownCharacters) else {
213
+ print("JWT Error: Could not decode base64 payload")
214
+ return nil
215
+ }
216
+
217
+ return try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
218
+ }
219
+ }
@@ -1,28 +1,41 @@
1
1
  import { NativeModules, Platform } from 'react-native';
2
2
 
3
+ /**
4
+ * This interface defines the full API surface of the native module.
5
+ * It is a complete and accurate representation of the methods exposed
6
+ * in SdkPianoioModule.kt.
7
+ */
3
8
  interface SdkPianoioType {
4
- initializeComposer(aid: string): Promise<any>;
5
- getComposer(): Promise<any>;
6
- addComposerTag(tag: string): Promise<any>;
7
- addComposerTags(tags: string[]): Promise<any>;
8
- setComposerZoneId(zoneId: string): Promise<any>;
9
- setComposerReferrer(referrer: string): Promise<any>;
10
- setComposerUrl(url: string): Promise<any>;
11
- setComposerCustomVariable(name: string, value: string): Promise<any>;
12
- setComposerUserToken(token: string): Promise<any>;
13
- executeComposer(): Promise<void>;
14
-
15
- executeExperience(): Promise<boolean>;
16
- showLogin(): Promise<boolean>;
17
- showTemplate(): Promise<boolean>;
18
- showForm(): Promise<boolean>;
19
- showRecommendations(): Promise<boolean>;
20
- nonSite(): Promise<boolean>;
21
- userSegmentTrue(): Promise<boolean>;
22
- userSegmentFalse(): Promise<boolean>;
23
- meterActive(): Promise<boolean>;
24
- meterExpired(): Promise<boolean>;
25
- composerExecutionCompleted(): Promise<boolean>;
9
+ // Initialization
10
+ initialize(aid: string): Promise<boolean>;
11
+
12
+ // Configuration
13
+ addTag(tag: string): Promise<boolean>;
14
+ addTags(tags: string[]): Promise<boolean>;
15
+ setZoneId(zoneId: string): Promise<boolean>;
16
+ setReferrer(referrer: string): Promise<boolean>;
17
+ setUrl(url: string): Promise<boolean>;
18
+ setUserToken(token: string): Promise<boolean>;
19
+ addCustomVariable(key: string, value: string): Promise<boolean>;
20
+ setCustomVariables(variables: { [key: string]: string }): Promise<boolean>;
21
+
22
+ // Execution
23
+ executeExperience(): Promise<any>;
24
+
25
+ // Authentication
26
+ signIn(): Promise<any>;
27
+ signOut(): Promise<any>;
28
+ getCurrentUser(): Promise<any>;
29
+ isAuthenticated(): Promise<any>;
30
+
31
+ // Status & Cleanup
32
+ getStatus(): Promise<any>;
33
+ isInitialized(): Promise<boolean>;
34
+ clearConfiguration(): Promise<boolean>;
35
+ removeTag(tag: string): Promise<boolean>;
36
+ removeCustomVariable(key: string): Promise<boolean>;
37
+ clearTags(): Promise<boolean>;
38
+ clearCustomVariables(): Promise<boolean>;
26
39
  }
27
40
 
28
41
  const SdkPianoio = NativeModules.SdkPianoio;