react-native-sdk-pianoio 0.3.2 → 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.
- package/README.md +176 -186
- package/android/build.gradle +29 -42
- package/android/gradle.properties +33 -14
- package/android/src/main/java/com/sdkpianoio/ComposerPianoImpl.kt +366 -0
- package/android/src/main/java/com/sdkpianoio/SdkPianoioModule.kt +281 -507
- package/android/src/main/java/com/sdkpianoio/TokenService.kt +139 -0
- package/android/test.sh +494 -0
- package/ios/ComposerPianoImpl.swift +128 -225
- package/ios/MyComposerDelegate.swift +142 -109
- package/ios/SdkPianoio.swift +69 -143
- package/ios/SdkPianoioBridge.m +18 -46
- package/ios/TokenService.swift +219 -0
- package/lib/commonjs/NativeSdkPianoio.ts +34 -10
- package/lib/commonjs/PianoComposer.js +69 -51
- package/lib/commonjs/PianoComposer.js.map +1 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/NativeSdkPianoio.ts +34 -10
- package/lib/module/PianoComposer.js +70 -51
- package/lib/module/PianoComposer.js.map +1 -1
- package/lib/module/index.js +0 -14
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/commonjs/src/NativeSdkPianoio.d.ts +27 -9
- package/lib/typescript/commonjs/src/NativeSdkPianoio.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/PianoComposer.d.ts +45 -18
- package/lib/typescript/commonjs/src/PianoComposer.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
- package/lib/typescript/module/src/NativeSdkPianoio.d.ts +27 -9
- package/lib/typescript/module/src/NativeSdkPianoio.d.ts.map +1 -1
- package/lib/typescript/module/src/PianoComposer.d.ts +45 -18
- package/lib/typescript/module/src/PianoComposer.d.ts.map +1 -1
- package/lib/typescript/module/src/index.d.ts.map +1 -1
- package/package.json +4 -1
- package/src/NativeSdkPianoio.ts +34 -10
- package/src/PianoComposer.tsx +76 -59
- package/src/index.tsx +0 -14
- package/android/src/main/AndroidManifestNew.xml +0 -2
- package/ios/services/TokenService.swift +0 -70
package/ios/SdkPianoio.swift
CHANGED
@@ -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
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
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
|
+
}
|
package/ios/SdkPianoioBridge.m
CHANGED
@@ -1,81 +1,53 @@
|
|
1
1
|
#import <React/RCTBridgeModule.h>
|
2
2
|
|
3
|
-
//
|
3
|
+
// This macro registers the Swift class 'SdkPianoio' with the React Native bridge.
|
4
4
|
@interface RCT_EXTERN_MODULE(SdkPianoio, NSObject)
|
5
5
|
|
6
|
-
//
|
7
|
-
// Le annotazioni @objc(...) nel suo file Swift definiscono queste esatte firme.
|
6
|
+
// MARK: - Initialization
|
8
7
|
|
9
|
-
RCT_EXTERN_METHOD(
|
8
|
+
RCT_EXTERN_METHOD(initialize:(NSString *)aid
|
10
9
|
resolver:(RCTPromiseResolveBlock)resolve
|
11
10
|
rejecter:(RCTPromiseRejectBlock)reject)
|
12
11
|
|
13
|
-
|
14
|
-
rejecter:(RCTPromiseRejectBlock)reject)
|
12
|
+
// MARK: - Configuration Methods
|
15
13
|
|
16
|
-
RCT_EXTERN_METHOD(
|
14
|
+
RCT_EXTERN_METHOD(addTag:(NSString *)tag
|
17
15
|
resolver:(RCTPromiseResolveBlock)resolve
|
18
16
|
rejecter:(RCTPromiseRejectBlock)reject)
|
19
17
|
|
20
|
-
RCT_EXTERN_METHOD(
|
18
|
+
RCT_EXTERN_METHOD(addTags:(NSArray<NSString *> *)tags
|
21
19
|
resolver:(RCTPromiseResolveBlock)resolve
|
22
20
|
rejecter:(RCTPromiseRejectBlock)reject)
|
23
21
|
|
24
|
-
RCT_EXTERN_METHOD(
|
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(
|
26
|
+
RCT_EXTERN_METHOD(setReferrer:(NSString *)referrer
|
30
27
|
resolver:(RCTPromiseResolveBlock)resolve
|
31
28
|
rejecter:(RCTPromiseRejectBlock)reject)
|
32
29
|
|
33
|
-
RCT_EXTERN_METHOD(
|
30
|
+
RCT_EXTERN_METHOD(setUrl:(NSString *)url
|
34
31
|
resolver:(RCTPromiseResolveBlock)resolve
|
35
32
|
rejecter:(RCTPromiseRejectBlock)reject)
|
36
33
|
|
37
|
-
RCT_EXTERN_METHOD(
|
34
|
+
RCT_EXTERN_METHOD(setUserToken:(NSString *)token
|
38
35
|
resolver:(RCTPromiseResolveBlock)resolve
|
39
36
|
rejecter:(RCTPromiseRejectBlock)reject)
|
40
37
|
|
41
|
-
RCT_EXTERN_METHOD(
|
38
|
+
RCT_EXTERN_METHOD(setCustomVariable:(NSString *)name
|
39
|
+
value:(NSString *)value
|
42
40
|
resolver:(RCTPromiseResolveBlock)resolve
|
43
41
|
rejecter:(RCTPromiseRejectBlock)reject)
|
44
42
|
|
45
|
-
|
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(
|
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
|
-
|
79
|
-
|
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,17 +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
|
-
|
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
|
5
23
|
executeExperience(): Promise<any>;
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
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>;
|
15
39
|
}
|
16
40
|
|
17
41
|
const SdkPianoio = NativeModules.SdkPianoio;
|