@package-kr/react-native-kakao-signin 0.0.1

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.
@@ -0,0 +1,256 @@
1
+ import Foundation
2
+
3
+ import KakaoSDKCommon
4
+ import KakaoSDKAuth
5
+ import KakaoSDKUser
6
+
7
+ @objc(RNKakaoSignin)
8
+ class RNKakaoSignin: NSObject {
9
+
10
+ // SDK 초기화
11
+ public override init() {
12
+ let appKey = Bundle.main.object(forInfoDictionaryKey: "KAKAO_APP_KEY") as? String
13
+ let customScheme = Bundle.main.object(forInfoDictionaryKey: "KAKAO_APP_SCHEME") as? String
14
+
15
+ RNKakaoSignin.configureSDK(appKey: appKey, customScheme: customScheme)
16
+
17
+ super.init()
18
+ }
19
+
20
+ // 메인 큐 초기화
21
+ @objc static func requiresMainQueueSetup() -> Bool { true }
22
+
23
+ // 카카오톡 로그인 URL 확인
24
+ @objc(isKakaoTalkLoginUrl:)
25
+ static func isKakaoTalkLoginUrl(_ url: URL) -> Bool {
26
+ return AuthApi.isKakaoTalkLoginUrl(url)
27
+ }
28
+
29
+ // 카카오톡 로그인 URL 처리
30
+ @objc(handleOpenUrl:)
31
+ static func handleOpenUrl(_ url: URL) -> Bool {
32
+ return AuthController.handleOpenUrl(url: url)
33
+ }
34
+
35
+ // 카카오 로그인
36
+ @objc(login:rejecter:)
37
+ func login(_ resolve: @escaping RCTPromiseResolveBlock,
38
+ rejecter reject: @escaping RCTPromiseRejectBlock) {
39
+ runOnMain {
40
+ let completion = self.tokenHandler(resolve, reject)
41
+
42
+ if UserApi.isKakaoTalkLoginAvailable() {
43
+ UserApi.shared.loginWithKakaoTalk(completion: completion)
44
+ return
45
+ }
46
+
47
+ UserApi.shared.loginWithKakaoAccount(completion: completion)
48
+ }
49
+ }
50
+
51
+ // 카카오계정 로그인
52
+ @objc(loginWithKakaoAccount:rejecter:)
53
+ func loginWithKakaoAccount(_ resolve: @escaping RCTPromiseResolveBlock,
54
+ rejecter reject: @escaping RCTPromiseRejectBlock) {
55
+ runOnMain { UserApi.shared.loginWithKakaoAccount(completion: self.tokenHandler(resolve, reject)) }
56
+ }
57
+
58
+ // 세션 처리
59
+
60
+ // 로그아웃
61
+ @objc(logout:rejecter:)
62
+ func logout(_ resolve: @escaping RCTPromiseResolveBlock,
63
+ rejecter reject: @escaping RCTPromiseRejectBlock) {
64
+ runOnMain { UserApi.shared.logout(completion: self.messageHandler(resolve, reject, "Successfully logged out")) }
65
+ }
66
+
67
+ // 연결 끊기
68
+ @objc(unlink:rejecter:)
69
+ func unlink(_ resolve: @escaping RCTPromiseResolveBlock,
70
+ rejecter reject: @escaping RCTPromiseRejectBlock) {
71
+ runOnMain { UserApi.shared.unlink(completion: self.messageHandler(resolve, reject, "Successfully unlinked")) }
72
+ }
73
+
74
+ // 토큰 정보 조회
75
+ @objc(getAccessToken:rejecter:)
76
+ func getAccessToken(_ resolve: @escaping RCTPromiseResolveBlock,
77
+ rejecter reject: @escaping RCTPromiseRejectBlock) {
78
+ runOnMain {
79
+ UserApi.shared.accessTokenInfo { info, error in
80
+ if let error = error { self.reject(reject, error) }
81
+ else {
82
+ resolve([
83
+ "accessToken": TokenManager.manager.getToken()?.accessToken as Any,
84
+ "expiresIn": info?.expiresIn as Any,
85
+ ])
86
+ }
87
+ }
88
+ }
89
+ }
90
+
91
+ // 프로필 조회
92
+ @objc(getProfile:rejecter:)
93
+ func getProfile(_ resolve: @escaping RCTPromiseResolveBlock,
94
+ rejecter reject: @escaping RCTPromiseRejectBlock) {
95
+ runOnMain {
96
+ UserApi.shared.me { user, error in
97
+ if let error = error { self.reject(reject, error) }
98
+ else {
99
+ let account = user?.kakaoAccount
100
+ let profile = account?.profile
101
+ resolve([
102
+ "id": user?.id as Any,
103
+ "name": account?.name as Any,
104
+ "email": account?.email as Any,
105
+ "nickname": profile?.nickname as Any,
106
+ "profileImageUrl": profile?.profileImageUrl?.absoluteString as Any,
107
+ "thumbnailImageUrl": profile?.thumbnailImageUrl?.absoluteString as Any,
108
+ "phoneNumber": account?.phoneNumber as Any,
109
+ "ageRange": account?.ageRange?.rawValue as Any,
110
+ "birthday": account?.birthday as Any,
111
+ "birthdayType": account?.birthdayType as Any,
112
+ "birthyear": account?.birthyear as Any,
113
+ "gender": account?.gender?.rawValue as Any,
114
+ "isEmailValid": account?.isEmailValid as Any,
115
+ "isEmailVerified": account?.isEmailVerified as Any,
116
+ "isKorean": account?.isKorean as Any,
117
+ "hasEmail": account?.hasEmail as Any,
118
+ "hasPhoneNumber": account?.hasPhoneNumber as Any,
119
+ "hasBirthday": account?.hasBirthday as Any,
120
+ "hasBirthyear": account?.hasBirthyear as Any,
121
+ "hasAgeRange": account?.hasAgeRange as Any,
122
+ "hasGender": account?.hasGender as Any,
123
+ "isDefaultImage": profile?.isDefaultImage as Any,
124
+ "isDefaultNickname": profile?.isDefaultNickname as Any,
125
+ "connectedAt": user?.connectedAt as Any,
126
+ "synchedAt": user?.synchedAt as Any,
127
+ "isLeapMonth": account?.isLeapMonth as Any,
128
+ "ci": account?.ci as Any,
129
+ "ciAuthenticatedAt": account?.ciAuthenticatedAt as Any,
130
+ "ageRangeNeedsAgreement": account?.ageRangeNeedsAgreement as Any,
131
+ "birthdayNeedsAgreement": account?.birthdayNeedsAgreement as Any,
132
+ "birthyearNeedsAgreement": account?.birthyearNeedsAgreement as Any,
133
+ "emailNeedsAgreement": account?.emailNeedsAgreement as Any,
134
+ "genderNeedsAgreement": account?.genderNeedsAgreement as Any,
135
+ "isKoreanNeedsAgreement": account?.isKoreanNeedsAgreement as Any,
136
+ "phoneNumberNeedsAgreement": account?.phoneNumberNeedsAgreement as Any,
137
+ "profileNeedsAgreement": account?.profileNeedsAgreement as Any,
138
+ "profileNicknameNeedsAgreement": account?.profileNicknameNeedsAgreement as Any,
139
+ "profileImageNeedsAgreement": account?.profileImageNeedsAgreement as Any,
140
+ "nameNeedsAgreement": account?.nameNeedsAgreement as Any,
141
+ "ciNeedsAgreement": account?.ciNeedsAgreement as Any,
142
+ ])
143
+ }
144
+ }
145
+ }
146
+ }
147
+
148
+ // 배송지 조회
149
+ @objc(shippingAddresses:rejecter:)
150
+ func shippingAddresses(_ resolve: @escaping RCTPromiseResolveBlock,
151
+ rejecter reject: @escaping RCTPromiseRejectBlock) {
152
+ runOnMain {
153
+ let fmt = RNKakaoSigninHelper.dateFormatter
154
+ UserApi.shared.shippingAddresses { addresses, error in
155
+ if let error = error { self.reject(reject, error) }
156
+ else {
157
+ resolve([
158
+ "userId": addresses?.userId as Any,
159
+ "needsAgreement": addresses?.needsAgreement as Any,
160
+ "shippingAddresses": addresses?.shippingAddresses?.map { addr in [
161
+ "id": addr.id as Any,
162
+ "name": addr.name as Any,
163
+ "isDefault": addr.isDefault as Any,
164
+ "updatedAt": fmt.string(from: addr.updatedAt!) as Any,
165
+ "type": addr.type?.rawValue as Any,
166
+ "baseAddress": addr.baseAddress as Any,
167
+ "detailAddress": addr.detailAddress as Any,
168
+ "receiverName": addr.receiverName as Any,
169
+ "receiverPhoneNumber1": addr.receiverPhoneNumber1 as Any,
170
+ "receiverPhoneNumber2": addr.receiverPhoneNumber2 as Any,
171
+ "zoneNumber": addr.zoneNumber as Any,
172
+ "zipCode": addr.zipCode as Any,
173
+ ]} as Any,
174
+ ])
175
+ }
176
+ }
177
+ }
178
+ }
179
+
180
+ // 서비스 약관 조회
181
+ @objc(serviceTerms:rejecter:)
182
+ func serviceTerms(_ resolve: @escaping RCTPromiseResolveBlock,
183
+ rejecter reject: @escaping RCTPromiseRejectBlock) {
184
+ runOnMain {
185
+ let fmt = RNKakaoSigninHelper.dateFormatter
186
+ UserApi.shared.serviceTerms { terms, error in
187
+ if let error = error { self.reject(reject, error) }
188
+ else {
189
+ var result: [String: Any] = [:]
190
+ if let userId = terms?.id { result["userId"] = userId }
191
+ if let serviceTerms = terms?.serviceTerms {
192
+ result["serviceTerms"] = serviceTerms.map { term -> [String: Any] in
193
+ var dict: [String: Any] = [
194
+ "tag": term.tag,
195
+ "agreed": term.agreed,
196
+ "required": term.required,
197
+ "revocable": term.revocable,
198
+ ]
199
+ if let agreedAt = term.agreedAt {
200
+ dict["agreedAt"] = fmt.string(from: agreedAt)
201
+ }
202
+ return dict
203
+ }
204
+ }
205
+ resolve(result)
206
+ }
207
+ }
208
+ }
209
+ }
210
+
211
+ // SDK 설정
212
+ private static func configureSDK(appKey: String?, customScheme: String?) {
213
+ guard let appKey = appKey else { return }
214
+
215
+ if let customScheme = customScheme {
216
+ KakaoSDK.initSDK(appKey: appKey, customScheme: customScheme)
217
+ return
218
+ }
219
+
220
+ KakaoSDK.initSDK(appKey: appKey)
221
+ }
222
+
223
+ // 메인 스레드 실행
224
+ private func runOnMain(_ action: @escaping () -> Void) {
225
+ DispatchQueue.main.async(execute: action)
226
+ }
227
+
228
+ // 토큰 응답 콜백
229
+ private func tokenHandler(
230
+ _ resolve: @escaping RCTPromiseResolveBlock,
231
+ _ reject: @escaping RCTPromiseRejectBlock
232
+ ) -> (OAuthToken?, Error?) -> Void {
233
+ return { token, error in
234
+ if let error = error { self.reject(reject, error) }
235
+ else { resolve(RNKakaoSigninHelper.tokenToDict(token)) }
236
+ }
237
+ }
238
+
239
+ // 메시지 응답 콜백
240
+ private func messageHandler(
241
+ _ resolve: @escaping RCTPromiseResolveBlock,
242
+ _ reject: @escaping RCTPromiseRejectBlock,
243
+ _ message: String
244
+ ) -> (Error?) -> Void {
245
+ return { error in
246
+ if let error = error { self.reject(reject, error) }
247
+ else { resolve(message) }
248
+ }
249
+ }
250
+
251
+ // 에러 변환
252
+ private func reject(_ reject: RCTPromiseRejectBlock, _ error: Error) {
253
+ let (code, message) = RNKakaoError.parse(error)
254
+ reject(code, message, error)
255
+ }
256
+ }
@@ -0,0 +1,25 @@
1
+ import Foundation
2
+
3
+ import KakaoSDKAuth
4
+
5
+ // 공통 헬퍼
6
+ enum RNKakaoSigninHelper {
7
+
8
+ static let dateFormatter: DateFormatter = {
9
+ let f = DateFormatter()
10
+ f.dateFormat = "yyyy-MM-dd HH:mm:ss"
11
+ return f
12
+ }()
13
+
14
+ static func tokenToDict(_ token: OAuthToken?) -> [String: Any] {
15
+ guard let token = token else { return [:] }
16
+ return [
17
+ "accessToken": token.accessToken,
18
+ "refreshToken": token.refreshToken,
19
+ "idToken": token.idToken as Any,
20
+ "accessTokenExpiresAt": dateFormatter.string(from: token.expiredAt),
21
+ "refreshTokenExpiresAt": dateFormatter.string(from: token.refreshTokenExpiredAt),
22
+ "scopes": token.scopes as Any,
23
+ ]
24
+ }
25
+ }
@@ -0,0 +1,148 @@
1
+ #import <UIKit/UIKit.h>
2
+ #import <objc/runtime.h>
3
+
4
+ // 카카오 로그인 URL을 체크하는 Swift 클래스
5
+ @interface RNKakaoSignin : NSObject
6
+ + (BOOL)isKakaoTalkLoginUrl:(NSURL *)url;
7
+ + (BOOL)handleOpenUrl:(NSURL *)url;
8
+ @end
9
+
10
+ typedef BOOL (*RNKakaoOpenURLIMP)(id, SEL, UIApplication *, NSURL *, NSDictionary *);
11
+ typedef BOOL (*RNKakaoContinueUserActivityIMP)(id, SEL, UIApplication *, NSUserActivity *, void (^)(NSArray<id<UIUserActivityRestoring>> *));
12
+ typedef void (*RNKakaoSetOriginalIMP)(IMP imp);
13
+
14
+ static RNKakaoOpenURLIMP rnKakaoOriginalOpenURLIMP = NULL;
15
+ static RNKakaoContinueUserActivityIMP rnKakaoOriginalContinueUserActivityIMP = NULL;
16
+
17
+ static void RNKakaoStoreOpenURLIMP(IMP imp);
18
+ static void RNKakaoStoreUserActivityIMP(IMP imp);
19
+ static BOOL RNKakaoHandleURL(NSURL *url);
20
+ static void RNKakaoInstallHandler(Class cls, SEL selector, IMP interceptor, const char *types, RNKakaoSetOriginalIMP storeOriginal, NSString *name);
21
+
22
+ // 카카오 로그인 복귀 URL 처리
23
+ static BOOL RNKakaoHandleURL(NSURL *url) {
24
+ if (url == nil) {
25
+ return NO;
26
+ }
27
+
28
+ if ([RNKakaoSignin isKakaoTalkLoginUrl:url]) {
29
+ return [RNKakaoSignin handleOpenUrl:url];
30
+ }
31
+
32
+ return NO;
33
+ }
34
+
35
+ // openURL 복귀 처리
36
+ static BOOL RNKakaoSignin_openURL(id self, SEL _cmd, UIApplication *app, NSURL *url, NSDictionary *options) {
37
+ NSLog(@"[RNKakaoSignin] openURL received: %@", url.absoluteString);
38
+
39
+ if (RNKakaoHandleURL(url)) {
40
+ return YES;
41
+ }
42
+
43
+ if (rnKakaoOriginalOpenURLIMP != NULL) {
44
+ return rnKakaoOriginalOpenURLIMP(self, _cmd, app, url, options);
45
+ }
46
+
47
+ return NO;
48
+ }
49
+
50
+ // universal link 복귀 처리
51
+ static BOOL RNKakaoSignin_continueUserActivity(
52
+ id self,
53
+ SEL _cmd,
54
+ UIApplication *app,
55
+ NSUserActivity *userActivity,
56
+ void (^restorationHandler)(NSArray<id<UIUserActivityRestoring>> *)
57
+ ) {
58
+ NSURL *url = userActivity.webpageURL;
59
+ NSLog(@"[RNKakaoSignin] continueUserActivity received: %@", url.absoluteString);
60
+
61
+ if (RNKakaoHandleURL(url)) {
62
+ return YES;
63
+ }
64
+
65
+ if (rnKakaoOriginalContinueUserActivityIMP != NULL) {
66
+ return rnKakaoOriginalContinueUserActivityIMP(self, _cmd, app, userActivity, restorationHandler);
67
+ }
68
+
69
+ return NO;
70
+ }
71
+
72
+ // 기존 openURL 저장
73
+ static void RNKakaoStoreOpenURLIMP(IMP imp) {
74
+ rnKakaoOriginalOpenURLIMP = (RNKakaoOpenURLIMP)imp;
75
+ }
76
+
77
+ // 기존 continueUserActivity 저장
78
+ static void RNKakaoStoreUserActivityIMP(IMP imp) {
79
+ rnKakaoOriginalContinueUserActivityIMP = (RNKakaoContinueUserActivityIMP)imp;
80
+ }
81
+
82
+ // delegate 메서드 주입
83
+ static void RNKakaoInstallHandler(
84
+ Class cls,
85
+ SEL selector,
86
+ IMP interceptor,
87
+ const char *types,
88
+ RNKakaoSetOriginalIMP storeOriginal,
89
+ NSString *name
90
+ ) {
91
+ Method method = class_getInstanceMethod(cls, selector);
92
+
93
+ if (method == NULL) {
94
+ class_addMethod(cls, selector, interceptor, types);
95
+ NSLog(@"[RNKakaoSignin] %@ added to %@", name, NSStringFromClass(cls));
96
+ return;
97
+ }
98
+
99
+ storeOriginal(method_getImplementation(method));
100
+ method_setImplementation(method, interceptor);
101
+ NSLog(@"[RNKakaoSignin] %@ swizzled on %@", name, NSStringFromClass(cls));
102
+ }
103
+
104
+ // 로더
105
+ @interface RNKakaoSigninLoader : NSObject
106
+ @end
107
+
108
+ @implementation RNKakaoSigninLoader
109
+
110
+ // 앱 delegate 주입
111
+ + (void)load {
112
+ int classCount = objc_getClassList(NULL, 0);
113
+ if (classCount <= 0) {
114
+ return;
115
+ }
116
+
117
+ Class *classes = (__unsafe_unretained Class *)malloc(sizeof(Class) * (NSUInteger)classCount);
118
+ classCount = objc_getClassList(classes, classCount);
119
+
120
+ // UIApplicationDelegate 채택 클래스 주입
121
+ for (int i = 0; i < classCount; i += 1) {
122
+ Class cls = classes[i];
123
+ if (!class_conformsToProtocol(cls, @protocol(UIApplicationDelegate))) {
124
+ continue;
125
+ }
126
+
127
+ RNKakaoInstallHandler(
128
+ cls,
129
+ @selector(application:openURL:options:),
130
+ (IMP)RNKakaoSignin_openURL,
131
+ "B@:@@@",
132
+ RNKakaoStoreOpenURLIMP,
133
+ @"openURL"
134
+ );
135
+ RNKakaoInstallHandler(
136
+ cls,
137
+ @selector(application:continueUserActivity:restorationHandler:),
138
+ (IMP)RNKakaoSignin_continueUserActivity,
139
+ "B@:@@@@",
140
+ RNKakaoStoreUserActivityIMP,
141
+ @"continueUserActivity"
142
+ );
143
+ }
144
+
145
+ free(classes);
146
+ }
147
+
148
+ @end
@@ -0,0 +1,36 @@
1
+ require "json"
2
+
3
+ # RCT_NEW_ARCH_ENABLED = 1일경우, install_modules_dependencies(s) 호출
4
+ fabric_enabled = ENV["RCT_NEW_ARCH_ENABLED"] == "1"
5
+
6
+ package = JSON.parse(File.read(File.join(__dir__, "package.json")))
7
+ kakao_sdk_version = "2.22.0"
8
+
9
+ Pod::Spec.new do |s|
10
+ s.name = "kakao-login"
11
+ s.version = package["version"]
12
+ s.summary = package["description"]
13
+ s.homepage = "https://github.com/Package-KR/react-native-kakao-signin"
14
+ s.license = "MIT"
15
+ s.authors = { "Package.kr" => "" }
16
+ s.platforms = { :ios => "13.0" }
17
+ s.framework = 'UIKit'
18
+ s.source = { :git => "https://github.com/Package-KR/react-native-kakao-signin.git", :tag => "#{s.version}" }
19
+
20
+ s.source_files = "ios/**/*.{h,m,mm,swift}"
21
+ s.requires_arc = true
22
+
23
+ if fabric_enabled
24
+ install_modules_dependencies(s)
25
+ else
26
+ s.dependency "React-Core"
27
+ end
28
+
29
+ if defined?($KakaoSDKVersion)
30
+ kakao_sdk_version = $KakaoSDKVersion
31
+ end
32
+
33
+ s.dependency 'KakaoSDKCommon', kakao_sdk_version
34
+ s.dependency 'KakaoSDKAuth', kakao_sdk_version
35
+ s.dependency 'KakaoSDKUser', kakao_sdk_version
36
+ end
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@package-kr/react-native-kakao-signin",
3
+ "version": "0.0.1",
4
+ "description": "React Native Kakao Login",
5
+ "main": "src/index",
6
+ "types": "src/index.d.ts",
7
+ "scripts": {
8
+ "android": "npm run android --workspace KakaoLoginExample",
9
+ "ios": "npm run ios --workspace KakaoLoginExample --",
10
+ "lint": "npm run lint --workspaces --if-present",
11
+ "start": "npm run start --workspace KakaoLoginExample",
12
+ "test": "npm run test --workspaces --if-present"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/Package-KR/react-native-kakao-signin"
17
+ },
18
+ "files": [
19
+ "src",
20
+ "ios",
21
+ "android",
22
+ "*.podspec",
23
+ "!KakaoLoginExample",
24
+ "!android/build",
25
+ "!ios/build"
26
+ ],
27
+ "publishConfig": {
28
+ "access": "public"
29
+ },
30
+ "keywords": [
31
+ "react-native",
32
+ "kakao",
33
+ "login"
34
+ ],
35
+ "license": "MIT",
36
+ "workspaces": [
37
+ "KakaoLoginExample"
38
+ ],
39
+ "peerDependencies": {
40
+ "react": "*",
41
+ "react-native": "*"
42
+ },
43
+ "codegenConfig": {
44
+ "name": "RNKakaoSigninSpec",
45
+ "type": "modules",
46
+ "jsSrcsDir": "src",
47
+ "android": {
48
+ "javaPackageName": "com.packagekr.kakao"
49
+ }
50
+ },
51
+ "engines": {
52
+ "node": ">= 22.11.0"
53
+ }
54
+ }
@@ -0,0 +1,15 @@
1
+ import type { TurboModule } from 'react-native';
2
+ import { TurboModuleRegistry } from 'react-native';
3
+
4
+ export interface Spec extends TurboModule {
5
+ login(): Promise<{ [key: string]: Object }>;
6
+ loginWithKakaoAccount(): Promise<{ [key: string]: Object }>;
7
+ logout(): Promise<string>;
8
+ unlink(): Promise<string>;
9
+ getProfile(): Promise<{ [key: string]: Object }>;
10
+ getAccessToken(): Promise<{ [key: string]: Object }>;
11
+ shippingAddresses(): Promise<{ [key: string]: Object }>;
12
+ serviceTerms(): Promise<{ [key: string]: Object }>;
13
+ }
14
+
15
+ export default TurboModuleRegistry.getEnforcing<Spec>('RNKakaoSignin');
package/src/index.ts ADDED
@@ -0,0 +1,45 @@
1
+ import NativeKakaoLogin from './NativeKakaoLogin';
2
+
3
+ import type { KakaoOAuthToken, KakaoProfile, KakaoAccessTokenInfo, KakaoShippingAddresses, KakaoServiceTerms } from './types';
4
+
5
+ // 카카오 로그인
6
+ export const login = (): Promise<KakaoOAuthToken> => {
7
+ return NativeKakaoLogin.login() as unknown as Promise<KakaoOAuthToken>;
8
+ };
9
+
10
+ // 카카오계정으로 로그인
11
+ export const loginWithKakaoAccount = (): Promise<KakaoOAuthToken> => {
12
+ return NativeKakaoLogin.loginWithKakaoAccount() as unknown as Promise<KakaoOAuthToken>;
13
+ };
14
+
15
+ // 로그아웃
16
+ export const logout = (): Promise<string> => {
17
+ return NativeKakaoLogin.logout();
18
+ };
19
+
20
+ // 연결 끊기
21
+ export const unlink = (): Promise<string> => {
22
+ return NativeKakaoLogin.unlink();
23
+ };
24
+
25
+ // 프로필 조회
26
+ export const getProfile = (): Promise<KakaoProfile> => {
27
+ return NativeKakaoLogin.getProfile() as unknown as Promise<KakaoProfile>;
28
+ };
29
+
30
+ // 토큰 정보 조회
31
+ export const getAccessToken = (): Promise<KakaoAccessTokenInfo> => {
32
+ return NativeKakaoLogin.getAccessToken() as unknown as Promise<KakaoAccessTokenInfo>;
33
+ };
34
+
35
+ // 배송지 조회
36
+ export const shippingAddresses = (): Promise<KakaoShippingAddresses> => {
37
+ return NativeKakaoLogin.shippingAddresses() as unknown as Promise<KakaoShippingAddresses>;
38
+ };
39
+
40
+ // 서비스 약관 조회
41
+ export const serviceTerms = (): Promise<KakaoServiceTerms> => {
42
+ return NativeKakaoLogin.serviceTerms() as unknown as Promise<KakaoServiceTerms>;
43
+ };
44
+
45
+ export * from './types';
@@ -0,0 +1,90 @@
1
+ export type KakaoOAuthToken = {
2
+ accessToken: string;
3
+ refreshToken: string;
4
+ idToken: string | null;
5
+ accessTokenExpiresAt: string;
6
+ refreshTokenExpiresAt: string;
7
+ scopes: string[] | null;
8
+ };
9
+
10
+ export type KakaoAccessTokenInfo = {
11
+ accessToken: string;
12
+ expiresIn: string;
13
+ };
14
+
15
+ export type KakaoShippingAddress = {
16
+ id: string;
17
+ name: string;
18
+ isDefault: boolean;
19
+ updatedAt: string;
20
+ type: string;
21
+ baseAddress: string;
22
+ detailAddress: string;
23
+ receiverName: string;
24
+ receiverPhoneNumber1: string;
25
+ receiverPhoneNumber2: string;
26
+ zoneNumber: string;
27
+ zipCode: string;
28
+ };
29
+
30
+ export type KakaoShippingAddresses = {
31
+ userId: string;
32
+ needsAgreement: boolean;
33
+ shippingAddresses: KakaoShippingAddress[];
34
+ };
35
+
36
+ export type KakaoServiceTerm = {
37
+ tag: string;
38
+ agreed: boolean;
39
+ required: boolean;
40
+ revocable: boolean;
41
+ agreedAt?: string;
42
+ };
43
+
44
+ export type KakaoServiceTerms = {
45
+ userId: string;
46
+ serviceTerms: KakaoServiceTerm[];
47
+ };
48
+
49
+ export type KakaoProfile = {
50
+ id: number | null;
51
+ nickname: string | null;
52
+ name: string | null;
53
+ email: string | null;
54
+ profileImageUrl: string | null;
55
+ thumbnailImageUrl: string | null;
56
+ gender: string | null;
57
+ ageRange: string | null;
58
+ birthday: string | null;
59
+ birthdayType: string | null;
60
+ birthyear: string | null;
61
+ phoneNumber: string | null;
62
+ isEmailValid: boolean | null;
63
+ isEmailVerified: boolean | null;
64
+ isKorean: boolean | null;
65
+ hasEmail: boolean | null;
66
+ hasPhoneNumber: boolean | null;
67
+ hasBirthday: boolean | null;
68
+ hasBirthyear: boolean | null;
69
+ hasAgeRange: boolean | null;
70
+ hasGender: boolean | null;
71
+ isDefaultImage: boolean | null;
72
+ isDefaultNickname: boolean | null;
73
+ connectedAt: string | null;
74
+ synchedAt: string | null;
75
+ isLeapMonth: boolean | null;
76
+ ci: string | null;
77
+ ciAuthenticatedAt: string | null;
78
+ emailNeedsAgreement: boolean | null;
79
+ profileNeedsAgreement: boolean | null;
80
+ phoneNumberNeedsAgreement: boolean | null;
81
+ genderNeedsAgreement: boolean | null;
82
+ ageRangeNeedsAgreement: boolean | null;
83
+ birthdayNeedsAgreement: boolean | null;
84
+ birthyearNeedsAgreement: boolean | null;
85
+ isKoreanNeedsAgreement: boolean | null;
86
+ profileNicknameNeedsAgreement: boolean | null;
87
+ profileImageNeedsAgreement: boolean | null;
88
+ nameNeedsAgreement: boolean | null;
89
+ ciNeedsAgreement: boolean | null;
90
+ };