@ph-cms/client-sdk 0.1.23 → 0.1.25
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 +88 -11
- package/bin/cli.js +1 -1
- package/dist/auth/firebase-provider.d.ts +2 -4
- package/dist/auth/firebase-provider.js +8 -18
- package/dist/client.d.ts +9 -0
- package/dist/client.js +11 -0
- package/dist/hooks/useAuth.d.ts +16 -20
- package/dist/hooks/useAuth.js +14 -4
- package/dist/hooks/useContent.d.ts +1 -1
- package/dist/hooks/useMedia.d.ts +1 -1
- package/dist/hooks/useUser.d.ts +1 -0
- package/dist/modules/auth.d.ts +8 -1
- package/dist/modules/auth.js +20 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -47,6 +47,8 @@ import type {
|
|
|
47
47
|
// Auth
|
|
48
48
|
LoginRequest,
|
|
49
49
|
RegisterRequest,
|
|
50
|
+
RegisterInput, // register() 훅에 전달하는 유니온 타입 (method: 'email' | 'firebase')
|
|
51
|
+
FirebaseRegisterRequest, // method: 'firebase' 방식의 페이로드 타입
|
|
50
52
|
RefreshTokenRequest,
|
|
51
53
|
FirebaseExchangeRequest,
|
|
52
54
|
AuthResponse,
|
|
@@ -113,7 +115,8 @@ SDK의 인증 시스템은 세 개의 레이어로 구성됩니다:
|
|
|
113
115
|
|---|---|---|
|
|
114
116
|
| `login()` | `POST /api/auth/login` | `setTokens()` → `refreshUser()` |
|
|
115
117
|
| `loginWithFirebase()` | `POST /api/auth/firebase/exchange` | `setTokens()` → `refreshUser()` |
|
|
116
|
-
| `register()` | `POST /api/auth/register` | `setTokens()` → `refreshUser()` |
|
|
118
|
+
| `register()` (method: 'email') | `POST /api/auth/register` | `setTokens()` → `refreshUser()` |
|
|
119
|
+
| `register()` (method: 'firebase') | `POST /api/auth/register` (provider: firebase:password) | `setTokens()` → `refreshUser()` |
|
|
117
120
|
| `logout()` | `POST /api/auth/logout` | `provider.logout()` → `refreshUser()` (상태 초기화) |
|
|
118
121
|
|
|
119
122
|
### Authentication Lifecycle
|
|
@@ -381,7 +384,7 @@ function AuthComponent() {
|
|
|
381
384
|
// 액션 (모두 Promise 반환)
|
|
382
385
|
login, // (data: LoginRequest) => Promise<AuthResponse>
|
|
383
386
|
loginWithFirebase, // (data: FirebaseExchangeRequest) => Promise<AuthResponse>
|
|
384
|
-
register, // (data:
|
|
387
|
+
register, // (data: RegisterInput) => Promise<AuthResponse> ← method: 'email' | 'firebase'
|
|
385
388
|
loginAnonymous, // (data?: AnonymousLoginRequest) => Promise<AuthResponse>
|
|
386
389
|
upgradeAnonymous, // (data: { email, password, display_name?, username? }) => Promise<UserDto>
|
|
387
390
|
logout, // () => Promise<void>
|
|
@@ -571,24 +574,85 @@ function UpgradeForm() {
|
|
|
571
574
|
|
|
572
575
|
#### 회원가입
|
|
573
576
|
|
|
577
|
+
`register()`는 `method` 필드로 이메일 방식과 Firebase 방식을 구분합니다.
|
|
578
|
+
`channelUid` 또는 `channelSlug` 중 하나는 필수입니다 (`PHCMSProvider`에 설정된 값이 자동으로 사용됩니다).
|
|
579
|
+
|
|
580
|
+
```ts
|
|
581
|
+
import type { RegisterInput } from '@ph-cms/client-sdk';
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
---
|
|
585
|
+
|
|
586
|
+
**방식 1 — 이메일/비밀번호 (`method: 'email'` 또는 생략)**
|
|
587
|
+
|
|
574
588
|
```tsx
|
|
575
589
|
function RegisterForm() {
|
|
576
590
|
const { register, registerStatus } = useAuth();
|
|
577
591
|
|
|
578
|
-
const handleRegister = async (
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
592
|
+
const handleRegister = async () => {
|
|
593
|
+
await register({
|
|
594
|
+
// method: 'email', // 생략 가능 (기본값)
|
|
595
|
+
email: 'user@example.com',
|
|
596
|
+
password: 'password123',
|
|
597
|
+
display_name: '홍길동',
|
|
598
|
+
termCodes: ['SERVICE_TERM', 'PRIVACY_TERM'], // 동의할 약관 코드 목록
|
|
599
|
+
// channelUid는 PHCMSProvider에 설정된 값이 자동 사용됨
|
|
600
|
+
// 명시적으로 지정하려면: channelUid: 'my-channel'
|
|
601
|
+
});
|
|
585
602
|
// 성공 → 자동으로 me() 호출 → 즉시 인증 상태로 전환
|
|
586
603
|
};
|
|
587
604
|
|
|
588
|
-
|
|
605
|
+
return (
|
|
606
|
+
<button onClick={handleRegister} disabled={registerStatus.isPending}>
|
|
607
|
+
{registerStatus.isPending ? '가입 중...' : '회원가입'}
|
|
608
|
+
</button>
|
|
609
|
+
);
|
|
589
610
|
}
|
|
590
611
|
```
|
|
591
612
|
|
|
613
|
+
---
|
|
614
|
+
|
|
615
|
+
**방식 2 — Firebase 회원가입 (`method: 'firebase'`)**
|
|
616
|
+
|
|
617
|
+
서버가 Firebase 계정 생성과 PH-CMS 계정 생성을 하나의 트랜잭션으로 처리합니다.
|
|
618
|
+
DB 트랜잭션 실패 시 서버가 Firebase 계정을 즉시 롤백하므로 고아 계정이 발생하지 않습니다.
|
|
619
|
+
|
|
620
|
+
클라이언트는 Firebase ID 토큰 없이 이메일/비밀번호만 전송합니다.
|
|
621
|
+
|
|
622
|
+
```tsx
|
|
623
|
+
function FirebaseRegisterForm() {
|
|
624
|
+
const { register, registerStatus } = useAuth();
|
|
625
|
+
|
|
626
|
+
const handleRegister = async () => {
|
|
627
|
+
await register({
|
|
628
|
+
method: 'firebase',
|
|
629
|
+
email: 'user@example.com',
|
|
630
|
+
password: 'password123',
|
|
631
|
+
display_name: '홍길동',
|
|
632
|
+
termCodes: ['SERVICE_TERM', 'PRIVACY_TERM'],
|
|
633
|
+
// channelUid는 PHCMSProvider에 설정된 값이 자동 사용됨
|
|
634
|
+
});
|
|
635
|
+
// 성공 → Firebase 계정 + PH-CMS 계정 동시 생성
|
|
636
|
+
// → 자동으로 me() 호출 → 즉시 인증 상태로 전환
|
|
637
|
+
};
|
|
638
|
+
|
|
639
|
+
return (
|
|
640
|
+
<button onClick={handleRegister} disabled={registerStatus.isPending}>
|
|
641
|
+
{registerStatus.isPending ? '가입 중...' : 'Firebase로 회원가입'}
|
|
642
|
+
</button>
|
|
643
|
+
);
|
|
644
|
+
}
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
> **Firebase 방식과 `loginWithFirebase()`의 차이**
|
|
648
|
+
>
|
|
649
|
+
> | | `register({ method: 'firebase' })` | `loginWithFirebase({ idToken })` |
|
|
650
|
+
> |---|---|---|
|
|
651
|
+
> | **목적** | 신규 가입 | 기존 Firebase 계정으로 로그인 / 신규 가입 |
|
|
652
|
+
> | **클라이언트 역할** | 이메일·비밀번호만 전송 | Firebase SDK로 직접 인증 후 ID 토큰 전달 |
|
|
653
|
+
> | **Firebase 계정 생성** | 서버가 처리 (롤백 보장) | 클라이언트가 처리 |
|
|
654
|
+
> | **용도** | 서버 사이드 Firebase 가입 플로우 | 소셜 로그인(Google 등) 또는 자체 Firebase 로그인 |
|
|
655
|
+
|
|
592
656
|
#### 로그아웃
|
|
593
657
|
|
|
594
658
|
```tsx
|
|
@@ -1238,6 +1302,18 @@ client.content // ContentModule
|
|
|
1238
1302
|
client.channel // ChannelModule
|
|
1239
1303
|
client.terms // TermsModule
|
|
1240
1304
|
client.media // MediaModule
|
|
1305
|
+
|
|
1306
|
+
await client.getToken() // 현재 유효한 PH-CMS access token 반환 (만료 시 자동 갱신, 없으면 null)
|
|
1307
|
+
```
|
|
1308
|
+
|
|
1309
|
+
`getToken()`은 PH-CMS SDK가 아닌 외부 서비스(예: 알림 서비스)를 클라이언트에서 직접 호출할 때 Authorization 헤더에 넣을 토큰을 가져오는 데 사용합니다.
|
|
1310
|
+
|
|
1311
|
+
```ts
|
|
1312
|
+
const token = await client.getToken();
|
|
1313
|
+
|
|
1314
|
+
const res = await fetch(`${NOTIFICATION_SERVICE_URL}/notifications`, {
|
|
1315
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
1316
|
+
});
|
|
1241
1317
|
```
|
|
1242
1318
|
|
|
1243
1319
|
`apiPrefix`는 생성 시 각 모듈에 직접 주입됩니다. 예를 들어 `apiPrefix: '/v2/api'`로 설정하면 모든 모듈의 요청 URL이 `/v2/api/contents/...`, `/v2/api/auth/...` 형태로 전송됩니다.
|
|
@@ -1334,7 +1410,8 @@ const result = await content.list({ channelUid: 'my-channel' });
|
|
|
1334
1410
|
|---|---|
|
|
1335
1411
|
| `login(data: LoginRequest)` | 이메일/비밀번호 로그인 → `AuthResponse` |
|
|
1336
1412
|
| `loginWithFirebase(data: FirebaseExchangeRequest)` | Firebase ID 토큰 교환 → `AuthResponse` |
|
|
1337
|
-
| `register(data: RegisterRequest)` | 회원가입 → `AuthResponse` |
|
|
1413
|
+
| `register(data: RegisterRequest)` | 이메일 회원가입 → `AuthResponse` (`channelUid` \| `channelSlug` 필수) |
|
|
1414
|
+
| `registerWithFirebase(data: FirebaseRegisterRequest)` | 서버 사이드 Firebase 회원가입 → `AuthResponse` (`channelUid` \| `channelSlug` 필수) |
|
|
1338
1415
|
| `me(params?: { channelUid?: string })` | 현재 사용자 프로필 조회 → `UserDto` |
|
|
1339
1416
|
| `refresh(refreshToken: string)` | 토큰 갱신 → `{ accessToken, refreshToken }` |
|
|
1340
1417
|
| `logout()` | 로그아웃 (프로바이더 토큰 삭제 + 서버 세션 무효화) |
|
package/bin/cli.js
CHANGED
|
@@ -30,15 +30,13 @@ export declare class FirebaseAuthProvider extends BaseAuthProvider {
|
|
|
30
30
|
expiryBufferMs?: number;
|
|
31
31
|
});
|
|
32
32
|
/**
|
|
33
|
-
* Returns
|
|
33
|
+
* Returns the current valid PH-CMS access token.
|
|
34
34
|
*
|
|
35
35
|
* 1. If a PH-CMS access token exists and is still valid, return it.
|
|
36
36
|
* 2. If the PH-CMS access token is expired (or will expire within
|
|
37
37
|
* `expiryBufferMs`), attempt an automatic refresh using the stored
|
|
38
38
|
* refresh token.
|
|
39
|
-
* 3. If no PH-CMS token exists
|
|
40
|
-
* the Firebase ID token (useful for the initial exchange call or if the
|
|
41
|
-
* server supports Firebase tokens directly).
|
|
39
|
+
* 3. If no PH-CMS token exists or refresh fails, return `null`.
|
|
42
40
|
*/
|
|
43
41
|
getToken(): Promise<string | null>;
|
|
44
42
|
/**
|
|
@@ -28,32 +28,22 @@ class FirebaseAuthProvider extends base_provider_1.BaseAuthProvider {
|
|
|
28
28
|
this.type = 'FIREBASE';
|
|
29
29
|
}
|
|
30
30
|
/**
|
|
31
|
-
* Returns
|
|
31
|
+
* Returns the current valid PH-CMS access token.
|
|
32
32
|
*
|
|
33
33
|
* 1. If a PH-CMS access token exists and is still valid, return it.
|
|
34
34
|
* 2. If the PH-CMS access token is expired (or will expire within
|
|
35
35
|
* `expiryBufferMs`), attempt an automatic refresh using the stored
|
|
36
36
|
* refresh token.
|
|
37
|
-
* 3. If no PH-CMS token exists
|
|
38
|
-
* the Firebase ID token (useful for the initial exchange call or if the
|
|
39
|
-
* server supports Firebase tokens directly).
|
|
37
|
+
* 3. If no PH-CMS token exists or refresh fails, return `null`.
|
|
40
38
|
*/
|
|
41
39
|
async getToken() {
|
|
42
|
-
if (this.accessToken)
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return refreshed;
|
|
48
|
-
// Refresh failed — fall through to Firebase ID token fallback.
|
|
49
|
-
}
|
|
50
|
-
else {
|
|
51
|
-
// Token is valid (or unparseable — let server decide).
|
|
52
|
-
return this.accessToken;
|
|
53
|
-
}
|
|
40
|
+
if (!this.accessToken)
|
|
41
|
+
return null;
|
|
42
|
+
const expired = this.isCurrentTokenExpired();
|
|
43
|
+
if (expired === true) {
|
|
44
|
+
return this.tryRefresh();
|
|
54
45
|
}
|
|
55
|
-
|
|
56
|
-
return this.getIdToken();
|
|
46
|
+
return this.accessToken;
|
|
57
47
|
}
|
|
58
48
|
/**
|
|
59
49
|
* Clears PH-CMS tokens **and** signs the user out of Firebase.
|
package/dist/client.d.ts
CHANGED
|
@@ -35,6 +35,15 @@ export declare class PHCMSClient {
|
|
|
35
35
|
private refreshQueue;
|
|
36
36
|
/** Exposes the auth provider so UI layers can check token state synchronously. */
|
|
37
37
|
get authProvider(): AuthProvider | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* Returns the current valid PH-CMS access token.
|
|
40
|
+
*
|
|
41
|
+
* Delegates to the configured {@link AuthProvider.getToken}, which handles
|
|
42
|
+
* expiry checks and automatic refresh internally.
|
|
43
|
+
*
|
|
44
|
+
* Returns `null` when no provider is configured or no valid token exists.
|
|
45
|
+
*/
|
|
46
|
+
getToken(): Promise<string | null>;
|
|
38
47
|
private readonly normalizedApiPrefix;
|
|
39
48
|
constructor(config: PHCMSClientConfig);
|
|
40
49
|
/**
|
package/dist/client.js
CHANGED
|
@@ -17,6 +17,17 @@ class PHCMSClient {
|
|
|
17
17
|
get authProvider() {
|
|
18
18
|
return this.config.auth;
|
|
19
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Returns the current valid PH-CMS access token.
|
|
22
|
+
*
|
|
23
|
+
* Delegates to the configured {@link AuthProvider.getToken}, which handles
|
|
24
|
+
* expiry checks and automatic refresh internally.
|
|
25
|
+
*
|
|
26
|
+
* Returns `null` when no provider is configured or no valid token exists.
|
|
27
|
+
*/
|
|
28
|
+
async getToken() {
|
|
29
|
+
return this.config.auth?.getToken() ?? null;
|
|
30
|
+
}
|
|
20
31
|
constructor(config) {
|
|
21
32
|
this.config = config;
|
|
22
33
|
/**
|
package/dist/hooks/useAuth.d.ts
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
import { FirebaseRegisterRequest, RegisterRequest } from '@ph-cms/api-contract';
|
|
2
|
+
type FirebaseRegisterInput = {
|
|
3
|
+
method: 'firebase';
|
|
4
|
+
} & FirebaseRegisterRequest;
|
|
5
|
+
type EmailRegisterInput = {
|
|
6
|
+
method?: 'email';
|
|
7
|
+
} & RegisterRequest;
|
|
8
|
+
/**
|
|
9
|
+
* register()에 전달할 수 있는 입력 타입.
|
|
10
|
+
* - method: 'firebase' → Firebase idToken 기반 가입 (FirebaseRegisterRequest)
|
|
11
|
+
* - method: 'email' (기본값) → 이메일/비밀번호 기반 가입 (RegisterRequest)
|
|
12
|
+
*/
|
|
13
|
+
export type RegisterInput = FirebaseRegisterInput | EmailRegisterInput;
|
|
1
14
|
/**
|
|
2
15
|
* Unified Auth Hook
|
|
3
16
|
* Returns both the current auth status and the actions.
|
|
@@ -150,16 +163,7 @@ export declare const useAuth: () => {
|
|
|
150
163
|
}[] | undefined;
|
|
151
164
|
};
|
|
152
165
|
accessToken: string;
|
|
153
|
-
}, Error,
|
|
154
|
-
email: string;
|
|
155
|
-
display_name: string;
|
|
156
|
-
username?: string | null | undefined;
|
|
157
|
-
password?: string | undefined;
|
|
158
|
-
provider?: string | undefined;
|
|
159
|
-
provider_subject?: string | undefined;
|
|
160
|
-
termCodes?: string[] | undefined;
|
|
161
|
-
channelUid?: string | undefined;
|
|
162
|
-
}, unknown>;
|
|
166
|
+
}, Error, RegisterInput, unknown>;
|
|
163
167
|
loginAnonymous: import("@tanstack/react-query").UseMutateAsyncFunction<{
|
|
164
168
|
refreshToken: string;
|
|
165
169
|
user: {
|
|
@@ -349,16 +353,7 @@ export declare const useAuth: () => {
|
|
|
349
353
|
}[] | undefined;
|
|
350
354
|
};
|
|
351
355
|
accessToken: string;
|
|
352
|
-
}, Error,
|
|
353
|
-
email: string;
|
|
354
|
-
display_name: string;
|
|
355
|
-
username?: string | null | undefined;
|
|
356
|
-
password?: string | undefined;
|
|
357
|
-
provider?: string | undefined;
|
|
358
|
-
provider_subject?: string | undefined;
|
|
359
|
-
termCodes?: string[] | undefined;
|
|
360
|
-
channelUid?: string | undefined;
|
|
361
|
-
}, unknown>;
|
|
356
|
+
}, Error, RegisterInput, unknown>;
|
|
362
357
|
loginAnonymousStatus: import("@tanstack/react-query").UseMutationResult<{
|
|
363
358
|
refreshToken: string;
|
|
364
359
|
user: {
|
|
@@ -551,3 +546,4 @@ export declare const useUpgradeAnonymous: () => import("@tanstack/react-query").
|
|
|
551
546
|
display_name?: string;
|
|
552
547
|
username?: string;
|
|
553
548
|
}, unknown>;
|
|
549
|
+
export {};
|
package/dist/hooks/useAuth.js
CHANGED
|
@@ -28,10 +28,20 @@ const useAuth = () => {
|
|
|
28
28
|
},
|
|
29
29
|
});
|
|
30
30
|
const registerMutation = (0, react_query_1.useMutation)({
|
|
31
|
-
mutationFn: (data) =>
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
mutationFn: (data) => {
|
|
32
|
+
if (data.method === 'firebase') {
|
|
33
|
+
const { method, channelUid: explicitChannelUid, ...rest } = data;
|
|
34
|
+
return client.auth.registerWithFirebase({
|
|
35
|
+
...rest,
|
|
36
|
+
channelUid: explicitChannelUid || channelUid,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
const { method, channelUid: explicitChannelUid, ...rest } = data;
|
|
40
|
+
return client.auth.register({
|
|
41
|
+
...rest,
|
|
42
|
+
channelUid: explicitChannelUid || channelUid,
|
|
43
|
+
});
|
|
44
|
+
},
|
|
35
45
|
onSuccess: async () => {
|
|
36
46
|
await refreshUser();
|
|
37
47
|
},
|
|
@@ -44,6 +44,7 @@ export declare const useCreateContent: () => import("@tanstack/react-query").Use
|
|
|
44
44
|
type: string;
|
|
45
45
|
title: string;
|
|
46
46
|
status?: string | undefined;
|
|
47
|
+
text?: string | null | undefined;
|
|
47
48
|
channelUid?: string | undefined;
|
|
48
49
|
channelSlug?: string | undefined;
|
|
49
50
|
geometry?: {
|
|
@@ -55,7 +56,6 @@ export declare const useCreateContent: () => import("@tanstack/react-query").Use
|
|
|
55
56
|
geometry?: any;
|
|
56
57
|
} | undefined;
|
|
57
58
|
image?: string | null | undefined;
|
|
58
|
-
text?: string | null | undefined;
|
|
59
59
|
attributes?: Record<string, any> | undefined;
|
|
60
60
|
summary?: string | null | undefined;
|
|
61
61
|
slug?: string | null | undefined;
|
package/dist/hooks/useMedia.d.ts
CHANGED
|
@@ -20,8 +20,8 @@ export declare const useUploadToS3: () => import("@tanstack/react-query").UseMut
|
|
|
20
20
|
}, unknown>;
|
|
21
21
|
export declare const useMediaDetail: (uid: string) => import("@tanstack/react-query").UseQueryResult<{
|
|
22
22
|
type: "image" | "video" | "audio" | "document" | "file";
|
|
23
|
-
uid: string;
|
|
24
23
|
url: string;
|
|
24
|
+
uid: string;
|
|
25
25
|
name: string;
|
|
26
26
|
mimeType: string;
|
|
27
27
|
size: number;
|
package/dist/hooks/useUser.d.ts
CHANGED
|
@@ -87,6 +87,7 @@ export declare const useUpdateProfile: () => import("@tanstack/react-query").Use
|
|
|
87
87
|
*/
|
|
88
88
|
export declare const useChannelTerms: () => import("@tanstack/react-query").UseQueryResult<{
|
|
89
89
|
code: string;
|
|
90
|
+
type: "text" | "url";
|
|
90
91
|
id: number;
|
|
91
92
|
version: string;
|
|
92
93
|
title: string;
|
package/dist/modules/auth.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AuthResponse, FirebaseExchangeRequest, LoginRequest, RegisterRequest, UserDto
|
|
1
|
+
import { AnonymousLoginRequest, AuthResponse, FirebaseExchangeRequest, FirebaseRegisterRequest, LoginRequest, RegisterRequest, UserDto } from "@ph-cms/api-contract";
|
|
2
2
|
import { AxiosInstance } from "axios";
|
|
3
3
|
import { AuthProvider } from "../auth/interfaces";
|
|
4
4
|
export declare class AuthModule {
|
|
@@ -15,6 +15,13 @@ export declare class AuthModule {
|
|
|
15
15
|
*/
|
|
16
16
|
loginWithFirebase(data: FirebaseExchangeRequest): Promise<AuthResponse>;
|
|
17
17
|
register(data: RegisterRequest): Promise<AuthResponse>;
|
|
18
|
+
/**
|
|
19
|
+
* 서버 사이드 Firebase 회원가입.
|
|
20
|
+
* 클라이언트는 idToken 없이 이메일/비밀번호를 전송하고,
|
|
21
|
+
* 서버가 Firebase 계정 생성과 백엔드 유저 생성을 원자적으로 처리한다.
|
|
22
|
+
* DB 실패 시 서버가 Firebase 계정을 롤백하므로 고아 계정이 발생하지 않는다.
|
|
23
|
+
*/
|
|
24
|
+
registerWithFirebase(data: FirebaseRegisterRequest): Promise<AuthResponse>;
|
|
18
25
|
me(params?: {
|
|
19
26
|
channelUid?: string;
|
|
20
27
|
channelSlug?: string;
|
package/dist/modules/auth.js
CHANGED
|
@@ -48,6 +48,26 @@ class AuthModule {
|
|
|
48
48
|
}
|
|
49
49
|
return response;
|
|
50
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* 서버 사이드 Firebase 회원가입.
|
|
53
|
+
* 클라이언트는 idToken 없이 이메일/비밀번호를 전송하고,
|
|
54
|
+
* 서버가 Firebase 계정 생성과 백엔드 유저 생성을 원자적으로 처리한다.
|
|
55
|
+
* DB 실패 시 서버가 Firebase 계정을 롤백하므로 고아 계정이 발생하지 않는다.
|
|
56
|
+
*/
|
|
57
|
+
async registerWithFirebase(data) {
|
|
58
|
+
const validation = api_contract_1.FirebaseRegisterSchema.safeParse(data);
|
|
59
|
+
if (!validation.success) {
|
|
60
|
+
throw new errors_1.ValidationError("Invalid Firebase register data", validation.error.errors);
|
|
61
|
+
}
|
|
62
|
+
const response = await this.client.post(`${this.prefix}/auth/register`, {
|
|
63
|
+
...data,
|
|
64
|
+
provider: 'firebase:password',
|
|
65
|
+
});
|
|
66
|
+
if (this.provider) {
|
|
67
|
+
this.provider.setTokens(response.accessToken, response.refreshToken);
|
|
68
|
+
}
|
|
69
|
+
return response;
|
|
70
|
+
}
|
|
51
71
|
async me(params) {
|
|
52
72
|
return this.client.get(`${this.prefix}/auth/me`, { params });
|
|
53
73
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ph-cms/client-sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.25",
|
|
4
4
|
"description": "Unified PH-CMS Client SDK (React + Core)",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"license": "MIT",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"LICENSE"
|
|
31
31
|
],
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@ph-cms/api-contract": "^0.1.
|
|
33
|
+
"@ph-cms/api-contract": "^0.1.9",
|
|
34
34
|
"@tanstack/react-query": "^5.0.0",
|
|
35
35
|
"axios": "^1.6.0",
|
|
36
36
|
"zod": "^3.22.4"
|