connectbase-client 3.38.0 → 3.39.2
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/CHANGELOG.md +54 -0
- package/README.md +1 -4
- package/dist/cli.js +33 -5
- package/dist/connect-base.umd.js +5 -5
- package/dist/index.d.mts +4 -102
- package/dist/index.d.ts +4 -102
- package/dist/index.js +1 -204
- package/dist/index.mjs +1 -203
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -14,15 +14,6 @@ var AuthError = class extends Error {
|
|
|
14
14
|
this.name = "AuthError";
|
|
15
15
|
}
|
|
16
16
|
};
|
|
17
|
-
var GuestSessionConflictError = class extends Error {
|
|
18
|
-
constructor() {
|
|
19
|
-
super(
|
|
20
|
-
"signInAsGuestMember refused: an active non-guest session is present in this client. Pass { allowOverrideExistingSession: true } to explicitly replace it, or call signOut() first."
|
|
21
|
-
);
|
|
22
|
-
this.code = "GUEST_SESSION_CONFLICT";
|
|
23
|
-
this.name = "GuestSessionConflictError";
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
17
|
var GameError = class extends Error {
|
|
27
18
|
constructor(init) {
|
|
28
19
|
super(init.message || init.code || "GameError");
|
|
@@ -776,21 +767,9 @@ function assertShape(value, shape, endpoint) {
|
|
|
776
767
|
}
|
|
777
768
|
|
|
778
769
|
// src/api/auth.ts
|
|
779
|
-
var GUEST_MEMBER_TOKEN_KEY_PREFIX = "cb_guest_";
|
|
780
|
-
function credentialToStorageKeyHash(credential) {
|
|
781
|
-
let hash = 0;
|
|
782
|
-
for (let i = 0; i < credential.length; i++) {
|
|
783
|
-
const char = credential.charCodeAt(i);
|
|
784
|
-
hash = (hash << 5) - hash + char;
|
|
785
|
-
hash = hash & hash;
|
|
786
|
-
}
|
|
787
|
-
return Math.abs(hash).toString(36);
|
|
788
|
-
}
|
|
789
770
|
var AuthAPI = class {
|
|
790
771
|
constructor(http) {
|
|
791
772
|
this.http = http;
|
|
792
|
-
this.guestMemberLoginPromise = null;
|
|
793
|
-
this.cachedGuestMemberTokenKey = null;
|
|
794
773
|
this.analytics = null;
|
|
795
774
|
}
|
|
796
775
|
/**
|
|
@@ -824,9 +803,7 @@ var AuthAPI = class {
|
|
|
824
803
|
* @example
|
|
825
804
|
* ```typescript
|
|
826
805
|
* const settings = await client.auth.getAuthSettings()
|
|
827
|
-
* if (settings.
|
|
828
|
-
* await client.auth.signInAsGuestMember()
|
|
829
|
-
* } else if (settings.allow_id_password_login) {
|
|
806
|
+
* if (settings.allow_id_password_login) {
|
|
830
807
|
* // 로그인 폼 표시
|
|
831
808
|
* } else if (settings.enabled_oauth_providers.includes('GOOGLE')) {
|
|
832
809
|
* // 구글 소셜 로그인 버튼 표시
|
|
@@ -904,66 +881,6 @@ var AuthAPI = class {
|
|
|
904
881
|
this.notifyVisitorTracker(response.member_id);
|
|
905
882
|
return response;
|
|
906
883
|
}
|
|
907
|
-
/**
|
|
908
|
-
* 앱 멤버 게스트 가입
|
|
909
|
-
* API Key로 인증된 앱에 게스트 멤버로 가입합니다.
|
|
910
|
-
* 실시간 채팅 등에서 JWT 토큰 기반 인증이 필요할 때 사용합니다.
|
|
911
|
-
* 로컬 스토리지에 저장된 토큰이 있으면 기존 계정으로 재로그인을 시도합니다.
|
|
912
|
-
* 동시 호출 시 중복 요청 방지 (race condition 방지)
|
|
913
|
-
*
|
|
914
|
-
* **활성 세션 가드 (3.22.0+)**
|
|
915
|
-
* OAuth/email/username 로 이미 로그인된 세션이 살아있는 채 이 메서드가 호출되면
|
|
916
|
-
* 메인 토큰 슬롯이 silent 로 게스트 토큰으로 덮어써져 사용자가 둔갑되는 회귀가
|
|
917
|
-
* 있었다 (platform-issue 019e6c5d). 이를 막기 위해 활성 비-게스트 세션이 감지되면
|
|
918
|
-
* 기본적으로 `GuestSessionConflictError` 를 던진다. 명시적으로 교체하려면
|
|
919
|
-
* `{ allowOverrideExistingSession: true }` 를 전달하거나 먼저 `signOut()` 을 호출할 것.
|
|
920
|
-
*
|
|
921
|
-
* @example
|
|
922
|
-
* ```typescript
|
|
923
|
-
* const guest = await client.auth.signInAsGuestMember()
|
|
924
|
-
* await client.realtime.connect({ accessToken: guest.access_token })
|
|
925
|
-
*
|
|
926
|
-
* // 활성 세션을 명시적으로 교체 (예: "게스트로 계속" 버튼)
|
|
927
|
-
* await client.auth.signInAsGuestMember({ allowOverrideExistingSession: true })
|
|
928
|
-
* ```
|
|
929
|
-
*/
|
|
930
|
-
async signInAsGuestMember(opts) {
|
|
931
|
-
if (this.guestMemberLoginPromise) {
|
|
932
|
-
return this.guestMemberLoginPromise;
|
|
933
|
-
}
|
|
934
|
-
if (!opts?.allowOverrideExistingSession && this.hasActiveNonGuestSession()) {
|
|
935
|
-
throw new GuestSessionConflictError();
|
|
936
|
-
}
|
|
937
|
-
this.guestMemberLoginPromise = this.executeGuestMemberLogin();
|
|
938
|
-
try {
|
|
939
|
-
return await this.guestMemberLoginPromise;
|
|
940
|
-
} finally {
|
|
941
|
-
this.guestMemberLoginPromise = null;
|
|
942
|
-
}
|
|
943
|
-
}
|
|
944
|
-
/**
|
|
945
|
-
* 현재 in-memory access token 이 "게스트 토큰이 아닌 다른 세션" 으로 판단되는지 확인.
|
|
946
|
-
*
|
|
947
|
-
* 판별 규칙:
|
|
948
|
-
* - access token 자체가 없으면 false (어떤 세션도 없음)
|
|
949
|
-
* - access token 이 만료됐으면 false (재로그인이 필요한 dead 상태)
|
|
950
|
-
* - persistence='none' 인 경우: 토큰은 메모리에만 존재. 우리는 그 토큰이
|
|
951
|
-
* 게스트인지 회원인지 분별할 메타가 메모리에 없다 → 보수적으로 true 처리.
|
|
952
|
-
* (회원이 가지고 있던 세션을 게스트가 덮어쓰는 게 더 큰 사고이므로
|
|
953
|
-
* false-positive < silent overwrite.)
|
|
954
|
-
* - persistence='localStorage'|'sessionStorage' 인 경우: 저장된 게스트 토큰과
|
|
955
|
-
* 현재 access token 이 일치하면 게스트 세션(false), 다르면 비-게스트(true).
|
|
956
|
-
*/
|
|
957
|
-
hasActiveNonGuestSession() {
|
|
958
|
-
const access = this.http.getAccessToken();
|
|
959
|
-
if (!access) return false;
|
|
960
|
-
if (this.isTokenExpired(access)) return false;
|
|
961
|
-
const stored = this.getStoredGuestMemberTokens();
|
|
962
|
-
if (!stored) {
|
|
963
|
-
return true;
|
|
964
|
-
}
|
|
965
|
-
return stored.accessToken !== access;
|
|
966
|
-
}
|
|
967
884
|
/**
|
|
968
885
|
* 현재 로그인한 멤버 정보 조회
|
|
969
886
|
* custom_data를 포함한 멤버 정보를 반환합니다.
|
|
@@ -1060,124 +977,6 @@ var AuthAPI = class {
|
|
|
1060
977
|
this.notifyVisitorTracker(null);
|
|
1061
978
|
}
|
|
1062
979
|
}
|
|
1063
|
-
/**
|
|
1064
|
-
* 저장된 게스트 멤버 토큰 삭제
|
|
1065
|
-
*/
|
|
1066
|
-
clearGuestMemberTokens() {
|
|
1067
|
-
const storage = this.http.getPersistenceStorage();
|
|
1068
|
-
if (!storage) return;
|
|
1069
|
-
storage.removeItem(this.getGuestMemberTokenKey());
|
|
1070
|
-
}
|
|
1071
|
-
// ===== Private Methods =====
|
|
1072
|
-
async executeGuestMemberLogin() {
|
|
1073
|
-
const storedData = this.getStoredGuestMemberTokens();
|
|
1074
|
-
if (storedData) {
|
|
1075
|
-
if (!this.isTokenExpired(storedData.accessToken)) {
|
|
1076
|
-
try {
|
|
1077
|
-
this.http.setTokens(storedData.accessToken, storedData.refreshToken);
|
|
1078
|
-
const memberInfo = await this.http.get(
|
|
1079
|
-
"/v1/public/app-members/me"
|
|
1080
|
-
);
|
|
1081
|
-
if (memberInfo.is_active) {
|
|
1082
|
-
this.notifyVisitorTracker(memberInfo.member_id);
|
|
1083
|
-
return {
|
|
1084
|
-
member_id: memberInfo.member_id,
|
|
1085
|
-
access_token: storedData.accessToken,
|
|
1086
|
-
refresh_token: storedData.refreshToken
|
|
1087
|
-
};
|
|
1088
|
-
}
|
|
1089
|
-
this.clearGuestMemberTokens();
|
|
1090
|
-
} catch {
|
|
1091
|
-
this.http.clearTokens();
|
|
1092
|
-
}
|
|
1093
|
-
}
|
|
1094
|
-
if (storedData.refreshToken && !this.isTokenExpired(storedData.refreshToken)) {
|
|
1095
|
-
try {
|
|
1096
|
-
const refreshed = await this.http.post(
|
|
1097
|
-
"/v1/auth/re-issue",
|
|
1098
|
-
{},
|
|
1099
|
-
{ headers: { "Authorization": `Bearer ${storedData.refreshToken}` }, skipAuth: true }
|
|
1100
|
-
);
|
|
1101
|
-
assertShape(
|
|
1102
|
-
refreshed,
|
|
1103
|
-
{
|
|
1104
|
-
access_token: { type: "string" },
|
|
1105
|
-
refresh_token: { type: "string" }
|
|
1106
|
-
},
|
|
1107
|
-
"auth.signInAsGuestMember.reissue"
|
|
1108
|
-
);
|
|
1109
|
-
this.http.setTokens(refreshed.access_token, refreshed.refresh_token);
|
|
1110
|
-
this.storeGuestMemberTokens(refreshed.access_token, refreshed.refresh_token, storedData.memberId);
|
|
1111
|
-
this.notifyVisitorTracker(storedData.memberId);
|
|
1112
|
-
return {
|
|
1113
|
-
member_id: storedData.memberId,
|
|
1114
|
-
access_token: refreshed.access_token,
|
|
1115
|
-
refresh_token: refreshed.refresh_token
|
|
1116
|
-
};
|
|
1117
|
-
} catch {
|
|
1118
|
-
this.clearGuestMemberTokens();
|
|
1119
|
-
}
|
|
1120
|
-
} else {
|
|
1121
|
-
this.clearGuestMemberTokens();
|
|
1122
|
-
}
|
|
1123
|
-
}
|
|
1124
|
-
const response = await this.http.post(
|
|
1125
|
-
"/v1/public/app-members",
|
|
1126
|
-
{},
|
|
1127
|
-
{ skipAuth: true }
|
|
1128
|
-
);
|
|
1129
|
-
assertShape(
|
|
1130
|
-
response,
|
|
1131
|
-
{
|
|
1132
|
-
access_token: { type: "string" },
|
|
1133
|
-
refresh_token: { type: "string" },
|
|
1134
|
-
member_id: { type: "string-or-number" }
|
|
1135
|
-
},
|
|
1136
|
-
"auth.signInAsGuestMember.new"
|
|
1137
|
-
);
|
|
1138
|
-
this.http.setTokens(response.access_token, response.refresh_token);
|
|
1139
|
-
this.storeGuestMemberTokens(response.access_token, response.refresh_token, response.member_id);
|
|
1140
|
-
this.notifyVisitorTracker(response.member_id);
|
|
1141
|
-
return response;
|
|
1142
|
-
}
|
|
1143
|
-
isTokenExpired(token) {
|
|
1144
|
-
try {
|
|
1145
|
-
const payload = JSON.parse(atob(token.split(".")[1]));
|
|
1146
|
-
const currentTime = Date.now() / 1e3;
|
|
1147
|
-
return payload.exp < currentTime;
|
|
1148
|
-
} catch {
|
|
1149
|
-
return true;
|
|
1150
|
-
}
|
|
1151
|
-
}
|
|
1152
|
-
getGuestMemberTokenKey() {
|
|
1153
|
-
if (this.cachedGuestMemberTokenKey) {
|
|
1154
|
-
return this.cachedGuestMemberTokenKey;
|
|
1155
|
-
}
|
|
1156
|
-
const credential = this.http.getCredential();
|
|
1157
|
-
if (!credential) {
|
|
1158
|
-
this.cachedGuestMemberTokenKey = `${GUEST_MEMBER_TOKEN_KEY_PREFIX}default`;
|
|
1159
|
-
} else {
|
|
1160
|
-
const keyHash = credentialToStorageKeyHash(credential);
|
|
1161
|
-
this.cachedGuestMemberTokenKey = `${GUEST_MEMBER_TOKEN_KEY_PREFIX}${keyHash}`;
|
|
1162
|
-
}
|
|
1163
|
-
return this.cachedGuestMemberTokenKey;
|
|
1164
|
-
}
|
|
1165
|
-
getStoredGuestMemberTokens() {
|
|
1166
|
-
const storage = this.http.getPersistenceStorage();
|
|
1167
|
-
if (!storage) return null;
|
|
1168
|
-
const stored = storage.getItem(this.getGuestMemberTokenKey());
|
|
1169
|
-
if (!stored) return null;
|
|
1170
|
-
try {
|
|
1171
|
-
return JSON.parse(stored);
|
|
1172
|
-
} catch {
|
|
1173
|
-
return null;
|
|
1174
|
-
}
|
|
1175
|
-
}
|
|
1176
|
-
storeGuestMemberTokens(accessToken, refreshToken, memberId) {
|
|
1177
|
-
const storage = this.http.getPersistenceStorage();
|
|
1178
|
-
if (!storage) return;
|
|
1179
|
-
storage.setItem(this.getGuestMemberTokenKey(), JSON.stringify({ accessToken, refreshToken, memberId }));
|
|
1180
|
-
}
|
|
1181
980
|
};
|
|
1182
981
|
|
|
1183
982
|
// src/api/database.ts
|
|
@@ -11340,7 +11139,6 @@ export {
|
|
|
11340
11139
|
GameError,
|
|
11341
11140
|
GameRoom,
|
|
11342
11141
|
GameRoomTransport,
|
|
11343
|
-
GuestSessionConflictError,
|
|
11344
11142
|
NativeAPI,
|
|
11345
11143
|
SessionManager,
|
|
11346
11144
|
VideoProcessingError,
|