@back23/promptly-sdk 2.14.2 → 2.18.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.
- package/README.md +361 -151
- package/dist/index.d.mts +8540 -521
- package/dist/index.d.ts +8540 -521
- package/dist/index.js +48 -4
- package/dist/index.mjs +48 -4
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -1,290 +1,495 @@
|
|
|
1
1
|
# @back23/promptly-sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Promptly AI CMS 공식 SDK - 헤드리스 CMS + 이커머스 + AI 기능을 제공합니다.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**버전: 2.18.0**
|
|
6
|
+
|
|
7
|
+
## 설치
|
|
6
8
|
|
|
7
9
|
```bash
|
|
8
10
|
npm install @back23/promptly-sdk
|
|
9
11
|
```
|
|
10
12
|
|
|
11
|
-
##
|
|
13
|
+
## 빠른 시작
|
|
12
14
|
|
|
13
15
|
```typescript
|
|
14
16
|
import { Promptly } from '@back23/promptly-sdk';
|
|
15
17
|
|
|
16
18
|
const client = new Promptly({
|
|
17
19
|
tenantId: 'your-tenant-id',
|
|
18
|
-
apiKey: 'pky_xxxxxxxxxxxxxxxx',
|
|
19
|
-
baseUrl: 'https://promptly.webbyon.com',
|
|
20
|
+
apiKey: 'pky_xxxxxxxxxxxxxxxx', // 필수 - Dashboard > Settings > API Tokens
|
|
21
|
+
baseUrl: 'https://promptly.webbyon.com', // 선택
|
|
22
|
+
|
|
23
|
+
// 토큰 자동 저장 (로그인 유지)
|
|
24
|
+
persistToken: true,
|
|
25
|
+
storageType: 'localStorage', // 또는 'sessionStorage'
|
|
26
|
+
onAuthStateChange: (token, user) => {
|
|
27
|
+
console.log('Auth changed:', user);
|
|
28
|
+
},
|
|
20
29
|
});
|
|
21
30
|
|
|
22
|
-
//
|
|
23
|
-
const { data: posts
|
|
31
|
+
// 블로그 조회
|
|
32
|
+
const { data: posts } = await client.blog.list();
|
|
24
33
|
|
|
25
|
-
//
|
|
34
|
+
// 상품 조회
|
|
26
35
|
const { data: products } = await client.shop.listProducts();
|
|
27
36
|
```
|
|
28
37
|
|
|
29
|
-
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## 인증 (Auth)
|
|
30
41
|
|
|
31
|
-
|
|
42
|
+
### 기본 설정
|
|
32
43
|
|
|
33
44
|
```typescript
|
|
34
45
|
const client = new Promptly({
|
|
35
46
|
tenantId: 'demo',
|
|
36
|
-
apiKey: 'pky_xxxxxxxxxxxxxxxx',
|
|
47
|
+
apiKey: 'pky_xxxxxxxxxxxxxxxx', // 필수
|
|
48
|
+
persistToken: true, // 토큰 자동 저장
|
|
37
49
|
});
|
|
38
50
|
```
|
|
39
51
|
|
|
40
|
-
|
|
52
|
+
### 토큰 자동 저장
|
|
53
|
+
|
|
54
|
+
`persistToken: true` 설정 시:
|
|
55
|
+
- **로그인**: `localStorage`에 자동 저장
|
|
56
|
+
- **새로고침**: 토큰 자동 복원
|
|
57
|
+
- **로그아웃**: 토큰 자동 삭제
|
|
58
|
+
- **저장 키**: `promptly_auth_token_{tenantId}`
|
|
41
59
|
|
|
42
60
|
```typescript
|
|
43
|
-
|
|
44
|
-
|
|
61
|
+
const client = new Promptly({
|
|
62
|
+
tenantId: 'demo',
|
|
63
|
+
apiKey: 'pky_xxx',
|
|
64
|
+
persistToken: true,
|
|
65
|
+
storageType: 'localStorage', // 기본값, 또는 'sessionStorage'
|
|
66
|
+
onAuthStateChange: (token, user) => {
|
|
67
|
+
// 로그인/로그아웃 시 호출
|
|
68
|
+
if (token) {
|
|
69
|
+
console.log('Logged in:', user);
|
|
70
|
+
} else {
|
|
71
|
+
console.log('Logged out');
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
```
|
|
45
76
|
|
|
46
|
-
|
|
47
|
-
const profile = await client.members.getProfile();
|
|
48
|
-
const orders = await client.orders.list();
|
|
77
|
+
### 로그인/회원가입
|
|
49
78
|
|
|
50
|
-
|
|
51
|
-
|
|
79
|
+
```typescript
|
|
80
|
+
// 회원가입
|
|
81
|
+
await client.auth.register({
|
|
82
|
+
name: 'John Doe',
|
|
83
|
+
email: 'john@example.com',
|
|
84
|
+
password: 'password',
|
|
85
|
+
password_confirmation: 'password',
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// 로그인 (토큰 자동 저장됨)
|
|
89
|
+
const { member, token } = await client.auth.login({
|
|
90
|
+
email: 'john@example.com',
|
|
91
|
+
password: 'password',
|
|
92
|
+
});
|
|
52
93
|
|
|
53
|
-
//
|
|
94
|
+
// 로그아웃 (토큰 자동 삭제됨)
|
|
54
95
|
await client.auth.logout();
|
|
96
|
+
|
|
97
|
+
// 인증 상태 확인
|
|
98
|
+
client.auth.isAuthenticated(); // true/false
|
|
99
|
+
|
|
100
|
+
// 현재 사용자
|
|
101
|
+
const me = await client.auth.me();
|
|
102
|
+
|
|
103
|
+
// 프로필 수정
|
|
104
|
+
await client.auth.updateProfile({ name: 'New Name' });
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### 소셜 로그인
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
// 사용 가능한 프로바이더
|
|
111
|
+
const providers = await client.auth.getSocialProviders();
|
|
112
|
+
// ['google', 'kakao', 'naver']
|
|
113
|
+
|
|
114
|
+
// 로그인 URL 획득
|
|
115
|
+
const { url } = await client.auth.getSocialAuthUrl('google');
|
|
116
|
+
window.location.href = url;
|
|
117
|
+
|
|
118
|
+
// 콜백 처리 (리다이렉트 후)
|
|
119
|
+
const { member, token } = await client.auth.socialCallback('google', code);
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### 비밀번호 재설정
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
// 재설정 이메일 발송
|
|
126
|
+
await client.auth.forgotPassword({ email: 'john@example.com' });
|
|
127
|
+
|
|
128
|
+
// 비밀번호 재설정
|
|
129
|
+
await client.auth.resetPassword({
|
|
130
|
+
token: 'reset-token',
|
|
131
|
+
email: 'john@example.com',
|
|
132
|
+
password: 'newpassword',
|
|
133
|
+
password_confirmation: 'newpassword',
|
|
134
|
+
});
|
|
55
135
|
```
|
|
56
136
|
|
|
57
|
-
|
|
137
|
+
---
|
|
58
138
|
|
|
59
|
-
|
|
139
|
+
## Blog API
|
|
60
140
|
|
|
61
141
|
```typescript
|
|
62
|
-
//
|
|
142
|
+
// 목록 조회
|
|
63
143
|
const { data, meta } = await client.blog.list({
|
|
64
144
|
page: 1,
|
|
65
145
|
per_page: 10,
|
|
66
|
-
category: 'tech',
|
|
67
|
-
tag: 'laravel',
|
|
68
|
-
search: 'keyword',
|
|
146
|
+
category: 'tech',
|
|
147
|
+
tag: 'laravel',
|
|
148
|
+
search: 'keyword',
|
|
69
149
|
});
|
|
70
150
|
|
|
71
|
-
//
|
|
151
|
+
// 상세 조회
|
|
72
152
|
const post = await client.blog.get('post-slug');
|
|
73
153
|
|
|
74
|
-
//
|
|
154
|
+
// 추천 글
|
|
75
155
|
const featured = await client.blog.featured(5);
|
|
76
156
|
|
|
77
|
-
//
|
|
157
|
+
// 카테고리/태그별 필터
|
|
78
158
|
const { data } = await client.blog.byCategory('news');
|
|
79
159
|
const { data } = await client.blog.byTag('featured');
|
|
80
160
|
|
|
81
|
-
//
|
|
82
|
-
const categories = await client.blog.categories();
|
|
83
|
-
const tags = await client.blog.tags();
|
|
161
|
+
// 카테고리/태그 목록
|
|
162
|
+
const categories = await client.blog.categories(); // string[]
|
|
163
|
+
const tags = await client.blog.tags(); // string[]
|
|
84
164
|
```
|
|
85
165
|
|
|
86
|
-
|
|
87
|
-
```typescript
|
|
88
|
-
interface BlogPost {
|
|
89
|
-
id: number;
|
|
90
|
-
title: string;
|
|
91
|
-
slug: string;
|
|
92
|
-
excerpt: string;
|
|
93
|
-
featured_image: string | null;
|
|
94
|
-
category: string | null;
|
|
95
|
-
tags: string[];
|
|
96
|
-
author: string;
|
|
97
|
-
views: number;
|
|
98
|
-
status: string;
|
|
99
|
-
published_at: string | null;
|
|
100
|
-
created_at: string;
|
|
101
|
-
content?: string; // Detail view only
|
|
102
|
-
updated_at?: string; // Detail view only
|
|
103
|
-
}
|
|
104
|
-
```
|
|
166
|
+
---
|
|
105
167
|
|
|
106
|
-
|
|
168
|
+
## Boards API
|
|
107
169
|
|
|
108
170
|
```typescript
|
|
109
|
-
//
|
|
171
|
+
// 게시판 목록
|
|
110
172
|
const { data: boards } = await client.boards.list();
|
|
111
173
|
|
|
112
|
-
//
|
|
174
|
+
// 게시판 조회
|
|
113
175
|
const board = await client.boards.get('board-slug');
|
|
114
176
|
|
|
115
|
-
//
|
|
177
|
+
// 게시글 목록
|
|
116
178
|
const { data: posts } = await client.boards.listPosts('board-slug', {
|
|
117
179
|
page: 1,
|
|
118
180
|
per_page: 10,
|
|
119
181
|
search: 'keyword',
|
|
120
182
|
});
|
|
121
183
|
|
|
122
|
-
//
|
|
184
|
+
// 게시글 상세
|
|
123
185
|
const post = await client.boards.getPost(postId);
|
|
124
186
|
|
|
125
|
-
//
|
|
187
|
+
// 게시글 작성 (인증 필요)
|
|
126
188
|
await client.boards.createPost({
|
|
127
189
|
board_id: 1,
|
|
128
190
|
title: 'Title',
|
|
129
191
|
content: 'Content',
|
|
192
|
+
is_secret: false,
|
|
130
193
|
});
|
|
131
194
|
|
|
132
|
-
//
|
|
195
|
+
// 게시글 수정/삭제
|
|
133
196
|
await client.boards.updatePost(postId, { title: 'New Title' });
|
|
134
197
|
await client.boards.deletePost(postId);
|
|
135
198
|
```
|
|
136
199
|
|
|
137
|
-
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Comments API
|
|
138
203
|
|
|
139
|
-
|
|
204
|
+
게시판, 블로그, 독립 댓글(방명록) 지원
|
|
140
205
|
|
|
141
206
|
```typescript
|
|
142
|
-
//
|
|
207
|
+
// 게시판 댓글
|
|
143
208
|
const { data } = await client.comments.boardPost(postId);
|
|
144
209
|
await client.comments.createBoardPost(postId, {
|
|
145
210
|
author_name: 'John',
|
|
146
|
-
content: 'Great
|
|
147
|
-
password: '1234', //
|
|
211
|
+
content: 'Great!',
|
|
212
|
+
password: '1234', // 비회원 댓글
|
|
148
213
|
});
|
|
149
214
|
|
|
150
|
-
//
|
|
215
|
+
// 블로그 댓글
|
|
151
216
|
const { data } = await client.comments.blogPost('post-slug');
|
|
152
217
|
await client.comments.createBlogPost('post-slug', {
|
|
153
|
-
author_name: 'Jane',
|
|
154
218
|
content: 'Nice article!',
|
|
155
219
|
});
|
|
156
220
|
|
|
157
|
-
//
|
|
221
|
+
// 독립 댓글 (방명록)
|
|
158
222
|
const { data } = await client.comments.standalone('guestbook');
|
|
159
223
|
await client.comments.createStandalone('guestbook', {
|
|
160
224
|
author_name: 'Visitor',
|
|
161
225
|
content: 'Hello!',
|
|
162
226
|
});
|
|
163
227
|
|
|
164
|
-
//
|
|
228
|
+
// 공통
|
|
165
229
|
await client.comments.update(commentId, { content: 'Updated' });
|
|
166
230
|
await client.comments.delete(commentId, { password: '1234' });
|
|
167
231
|
await client.comments.like(commentId);
|
|
168
232
|
```
|
|
169
233
|
|
|
170
|
-
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## Shop API
|
|
237
|
+
|
|
238
|
+
### 상품
|
|
171
239
|
|
|
172
240
|
```typescript
|
|
173
|
-
//
|
|
241
|
+
// 상품 목록
|
|
174
242
|
const { data: products } = await client.shop.listProducts({
|
|
175
|
-
category: '
|
|
243
|
+
category: 'shoes',
|
|
176
244
|
is_featured: true,
|
|
245
|
+
min_price: 10000,
|
|
246
|
+
max_price: 50000,
|
|
247
|
+
search: 'keyword',
|
|
177
248
|
});
|
|
249
|
+
|
|
250
|
+
// 상품 상세
|
|
178
251
|
const product = await client.shop.getProduct('product-slug');
|
|
252
|
+
|
|
253
|
+
// 추천 상품
|
|
179
254
|
const featured = await client.shop.featuredProducts(8);
|
|
255
|
+
|
|
256
|
+
// 카테고리 목록
|
|
180
257
|
const categories = await client.shop.listCategories();
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### 상품 리뷰
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
// 리뷰 목록
|
|
264
|
+
const { data: reviews, stats } = await client.shop.getProductReviews('product-slug', {
|
|
265
|
+
page: 1,
|
|
266
|
+
per_page: 10,
|
|
267
|
+
rating: 5, // 별점 필터
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
// 리뷰 통계
|
|
271
|
+
// stats = { average_rating: 4.5, total_count: 123, rating_counts: { 5: 80, 4: 30, ... } }
|
|
272
|
+
|
|
273
|
+
// 리뷰 작성 (인증 + 구매 필요)
|
|
274
|
+
await client.shop.createProductReview('product-slug', {
|
|
275
|
+
rating: 5,
|
|
276
|
+
title: 'Great product!',
|
|
277
|
+
content: 'Highly recommended.',
|
|
278
|
+
images: ['https://...'],
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
// 리뷰 수정/삭제
|
|
282
|
+
await client.shop.updateProductReview(reviewId, { rating: 4 });
|
|
283
|
+
await client.shop.deleteProductReview(reviewId);
|
|
284
|
+
|
|
285
|
+
// 도움이 됐어요
|
|
286
|
+
await client.shop.markReviewHelpful(reviewId);
|
|
287
|
+
|
|
288
|
+
// 내 리뷰 목록
|
|
289
|
+
const { data: myReviews } = await client.shop.getMyReviews();
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### 장바구니 (인증 필요)
|
|
181
293
|
|
|
182
|
-
|
|
294
|
+
```typescript
|
|
295
|
+
// 장바구니 조회
|
|
183
296
|
const cart = await client.shop.getCart();
|
|
184
|
-
|
|
297
|
+
|
|
298
|
+
// 상품 추가
|
|
299
|
+
await client.shop.addToCart({
|
|
300
|
+
product_id: 1,
|
|
301
|
+
quantity: 2,
|
|
302
|
+
variant_id: 3, // 옵션 상품
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
// 수량 변경
|
|
185
306
|
await client.shop.updateCartItem(itemId, { quantity: 3 });
|
|
307
|
+
|
|
308
|
+
// 상품 제거
|
|
186
309
|
await client.shop.removeFromCart(itemId);
|
|
310
|
+
|
|
311
|
+
// 장바구니 비우기
|
|
187
312
|
await client.shop.clearCart();
|
|
313
|
+
```
|
|
188
314
|
|
|
189
|
-
|
|
315
|
+
### 주문 (인증 필요)
|
|
316
|
+
|
|
317
|
+
```typescript
|
|
318
|
+
// 주문 생성
|
|
190
319
|
const order = await client.shop.createOrder({
|
|
191
320
|
orderer_name: 'John Doe',
|
|
192
321
|
orderer_email: 'john@example.com',
|
|
193
|
-
orderer_phone: '
|
|
322
|
+
orderer_phone: '010-1234-5678',
|
|
194
323
|
shipping_name: 'John Doe',
|
|
195
|
-
shipping_phone: '
|
|
324
|
+
shipping_phone: '010-1234-5678',
|
|
196
325
|
shipping_zipcode: '12345',
|
|
197
|
-
shipping_address: '
|
|
198
|
-
shipping_address_detail: '
|
|
326
|
+
shipping_address: '서울시 강남구',
|
|
327
|
+
shipping_address_detail: '101동 101호',
|
|
328
|
+
shipping_memo: '부재시 경비실',
|
|
329
|
+
coupon_code: 'SAVE10',
|
|
199
330
|
});
|
|
331
|
+
|
|
332
|
+
// 주문 목록
|
|
200
333
|
const { data: orders } = await client.shop.listOrders();
|
|
334
|
+
|
|
335
|
+
// 주문 상세
|
|
201
336
|
const orderDetail = await client.shop.getOrder(orderId);
|
|
337
|
+
|
|
338
|
+
// 주문 취소
|
|
202
339
|
await client.shop.cancelOrder(orderId);
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
### 결제 (토스페이먼츠)
|
|
203
343
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
const
|
|
344
|
+
```typescript
|
|
345
|
+
// 결제 준비
|
|
346
|
+
const payment = await client.shop.preparePayment({
|
|
347
|
+
order_number: 'ORD-123',
|
|
348
|
+
success_url: 'https://mysite.com/payment/success',
|
|
349
|
+
fail_url: 'https://mysite.com/payment/fail',
|
|
350
|
+
});
|
|
351
|
+
// payment = { client_key, order_id, order_name, amount, customer_name, ... }
|
|
352
|
+
|
|
353
|
+
// 결제 승인 (토스 결제 완료 후)
|
|
354
|
+
await client.shop.confirmPayment({
|
|
355
|
+
payment_key: 'toss_payment_key',
|
|
356
|
+
order_id: 'ORD-123',
|
|
357
|
+
amount: 50000,
|
|
358
|
+
});
|
|
207
359
|
```
|
|
208
360
|
|
|
209
|
-
###
|
|
361
|
+
### 쿠폰
|
|
362
|
+
|
|
363
|
+
```typescript
|
|
364
|
+
// 쿠폰 검증
|
|
365
|
+
const result = await client.shop.validateCoupon('SAVE10', 50000);
|
|
366
|
+
// { valid: true, discount_amount: 5000, coupon: { ... } }
|
|
367
|
+
|
|
368
|
+
// 내 쿠폰 목록
|
|
369
|
+
const coupons = await client.shop.myCoupons();
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
### 배송 설정
|
|
373
|
+
|
|
374
|
+
```typescript
|
|
375
|
+
const settings = await client.shop.getShippingSettings();
|
|
376
|
+
// { base_fee, free_shipping_threshold, ... }
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
---
|
|
380
|
+
|
|
381
|
+
## Reservation API
|
|
382
|
+
|
|
383
|
+
### 공개 API
|
|
210
384
|
|
|
211
385
|
```typescript
|
|
212
|
-
//
|
|
386
|
+
// 예약 설정
|
|
213
387
|
const settings = await client.reservation.getSettings();
|
|
388
|
+
|
|
389
|
+
// 서비스 목록
|
|
214
390
|
const services = await client.reservation.listServices();
|
|
391
|
+
|
|
392
|
+
// 담당자 목록
|
|
215
393
|
const staff = await client.reservation.listStaff(serviceId);
|
|
216
394
|
|
|
217
|
-
//
|
|
395
|
+
// 예약 가능 날짜
|
|
218
396
|
const dates = await client.reservation.getAvailableDates({
|
|
219
397
|
service_id: 1,
|
|
220
398
|
staff_id: 2,
|
|
221
399
|
start_date: '2026-01-01',
|
|
222
400
|
end_date: '2026-01-31',
|
|
223
401
|
});
|
|
402
|
+
|
|
403
|
+
// 예약 가능 시간
|
|
224
404
|
const slots = await client.reservation.getAvailableSlots({
|
|
225
405
|
service_id: 1,
|
|
226
406
|
date: '2026-01-15',
|
|
227
407
|
staff_id: 2,
|
|
228
408
|
});
|
|
409
|
+
```
|
|
229
410
|
|
|
230
|
-
|
|
231
|
-
|
|
411
|
+
### 예약 관리 (인증 필요)
|
|
412
|
+
|
|
413
|
+
```typescript
|
|
414
|
+
// 예약 생성
|
|
415
|
+
await client.reservation.create({
|
|
232
416
|
service_id: 1,
|
|
233
417
|
staff_id: 2,
|
|
234
418
|
reservation_date: '2026-01-15',
|
|
235
419
|
start_time: '14:00',
|
|
236
420
|
customer_name: 'John Doe',
|
|
237
|
-
customer_phone: '
|
|
421
|
+
customer_phone: '010-1234-5678',
|
|
422
|
+
customer_email: 'john@example.com',
|
|
423
|
+
notes: '요청사항',
|
|
238
424
|
});
|
|
239
425
|
|
|
240
|
-
//
|
|
426
|
+
// 내 예약 목록
|
|
241
427
|
const { data } = await client.reservation.list({ status: 'confirmed' });
|
|
428
|
+
|
|
429
|
+
// 다가오는/지난 예약
|
|
242
430
|
const upcoming = await client.reservation.upcoming(5);
|
|
243
431
|
const past = await client.reservation.past(10);
|
|
244
|
-
|
|
432
|
+
|
|
433
|
+
// 예약 취소
|
|
434
|
+
await client.reservation.cancel('RES-20260115-001', '일정 변경');
|
|
245
435
|
```
|
|
246
436
|
|
|
247
|
-
|
|
437
|
+
---
|
|
438
|
+
|
|
439
|
+
## Forms API
|
|
248
440
|
|
|
249
441
|
```typescript
|
|
250
|
-
//
|
|
442
|
+
// 폼 목록
|
|
251
443
|
const { data: forms } = await client.forms.list();
|
|
252
444
|
|
|
253
|
-
//
|
|
445
|
+
// 폼 상세 (필드 정보 포함)
|
|
254
446
|
const form = await client.forms.get('contact');
|
|
255
447
|
|
|
256
|
-
//
|
|
448
|
+
// 폼 제출
|
|
257
449
|
await client.forms.submit('contact', {
|
|
258
450
|
name: 'John Doe',
|
|
259
451
|
email: 'john@example.com',
|
|
260
452
|
message: 'Hello!',
|
|
261
453
|
});
|
|
262
454
|
|
|
263
|
-
//
|
|
455
|
+
// 내 제출 목록 (인증 필요)
|
|
264
456
|
const { data: submissions } = await client.forms.mySubmissions();
|
|
265
457
|
```
|
|
266
458
|
|
|
267
|
-
|
|
459
|
+
---
|
|
460
|
+
|
|
461
|
+
## Media API (인증 필요)
|
|
268
462
|
|
|
269
463
|
```typescript
|
|
270
|
-
//
|
|
464
|
+
// 파일 업로드
|
|
271
465
|
const media = await client.media.upload(file);
|
|
466
|
+
|
|
467
|
+
// 여러 파일 업로드
|
|
272
468
|
const mediaList = await client.media.uploadMultiple([file1, file2]);
|
|
273
469
|
|
|
274
|
-
//
|
|
470
|
+
// 내 미디어 목록
|
|
275
471
|
const { data: myMedia } = await client.media.list({ type: 'image/jpeg' });
|
|
472
|
+
|
|
473
|
+
// 미디어 삭제
|
|
276
474
|
await client.media.delete(mediaId);
|
|
277
475
|
```
|
|
278
476
|
|
|
279
|
-
|
|
477
|
+
---
|
|
478
|
+
|
|
479
|
+
## Custom Entities API
|
|
480
|
+
|
|
481
|
+
동적 데이터 구조 생성/관리
|
|
280
482
|
|
|
281
|
-
|
|
483
|
+
### 엔티티 정의
|
|
282
484
|
|
|
283
485
|
```typescript
|
|
284
|
-
//
|
|
486
|
+
// 엔티티 목록
|
|
285
487
|
const entities = await client.entities.list();
|
|
488
|
+
|
|
489
|
+
// 엔티티 조회
|
|
286
490
|
const entity = await client.entities.get('customers');
|
|
287
491
|
|
|
492
|
+
// 엔티티 생성
|
|
288
493
|
await client.entities.create({
|
|
289
494
|
name: 'Customer',
|
|
290
495
|
slug: 'customers',
|
|
@@ -300,74 +505,57 @@ await client.entities.create({
|
|
|
300
505
|
},
|
|
301
506
|
});
|
|
302
507
|
|
|
508
|
+
// 엔티티 수정/삭제
|
|
303
509
|
await client.entities.update('customers', { name: 'Clients' });
|
|
304
|
-
await client.entities.delete('customers', true);
|
|
510
|
+
await client.entities.delete('customers', true); // force
|
|
511
|
+
```
|
|
305
512
|
|
|
306
|
-
|
|
513
|
+
### 레코드
|
|
514
|
+
|
|
515
|
+
```typescript
|
|
516
|
+
// 레코드 목록
|
|
307
517
|
const { data: records } = await client.entities.listRecords('customers', {
|
|
308
518
|
search: 'ACME',
|
|
309
519
|
filters: JSON.stringify({ status: 'active' }),
|
|
310
520
|
});
|
|
521
|
+
|
|
522
|
+
// 레코드 조회
|
|
311
523
|
const record = await client.entities.getRecord('customers', 1);
|
|
312
524
|
|
|
525
|
+
// 레코드 생성
|
|
313
526
|
await client.entities.createRecord('customers', {
|
|
314
527
|
company: 'ACME Corp',
|
|
315
528
|
email: 'contact@acme.com',
|
|
316
529
|
status: 'active',
|
|
317
530
|
});
|
|
531
|
+
|
|
532
|
+
// 레코드 수정/삭제
|
|
318
533
|
await client.entities.updateRecord('customers', 1, { status: 'inactive' });
|
|
319
534
|
await client.entities.deleteRecord('customers', 1);
|
|
535
|
+
```
|
|
320
536
|
|
|
321
|
-
|
|
537
|
+
### TypeScript 지원
|
|
538
|
+
|
|
539
|
+
```typescript
|
|
322
540
|
interface Customer {
|
|
323
541
|
company: string;
|
|
324
542
|
email: string;
|
|
325
543
|
status: 'active' | 'inactive';
|
|
326
544
|
}
|
|
545
|
+
|
|
327
546
|
const customers = client.entities.typed<Customer>('customers');
|
|
328
|
-
const { data } = await customers.list();
|
|
547
|
+
const { data } = await customers.list(); // data: Customer[]
|
|
329
548
|
```
|
|
330
549
|
|
|
331
|
-
|
|
550
|
+
---
|
|
332
551
|
|
|
333
|
-
|
|
334
|
-
// Register
|
|
335
|
-
await client.auth.register({
|
|
336
|
-
name: 'John Doe',
|
|
337
|
-
email: 'john@example.com',
|
|
338
|
-
password: 'password',
|
|
339
|
-
password_confirmation: 'password',
|
|
340
|
-
});
|
|
552
|
+
## 응답 타입
|
|
341
553
|
|
|
342
|
-
|
|
343
|
-
const { member, token } = await client.auth.login({
|
|
344
|
-
email: 'john@example.com',
|
|
345
|
-
password: 'password',
|
|
346
|
-
});
|
|
347
|
-
await client.auth.logout();
|
|
348
|
-
|
|
349
|
-
// Profile
|
|
350
|
-
const me = await client.auth.me();
|
|
351
|
-
await client.auth.updateProfile({ name: 'New Name' });
|
|
352
|
-
|
|
353
|
-
// Token management
|
|
354
|
-
client.setToken('saved-token');
|
|
355
|
-
const token = client.getToken();
|
|
356
|
-
client.isAuthenticated();
|
|
357
|
-
|
|
358
|
-
// Social login
|
|
359
|
-
const providers = await client.auth.getSocialProviders();
|
|
360
|
-
const { url } = await client.auth.getSocialAuthUrl('google');
|
|
361
|
-
const response = await client.auth.socialCallback('google', code);
|
|
362
|
-
```
|
|
363
|
-
|
|
364
|
-
## Response Types
|
|
365
|
-
|
|
366
|
-
All list APIs return a consistent format:
|
|
554
|
+
모든 목록 API는 일관된 형식 반환:
|
|
367
555
|
|
|
368
556
|
```typescript
|
|
369
557
|
interface ListResponse<T> {
|
|
370
|
-
data: T[]; //
|
|
558
|
+
data: T[]; // 항상 배열, null 아님
|
|
371
559
|
meta: {
|
|
372
560
|
current_page: number;
|
|
373
561
|
last_page: number;
|
|
@@ -379,7 +567,9 @@ interface ListResponse<T> {
|
|
|
379
567
|
}
|
|
380
568
|
```
|
|
381
569
|
|
|
382
|
-
|
|
570
|
+
---
|
|
571
|
+
|
|
572
|
+
## 에러 처리
|
|
383
573
|
|
|
384
574
|
```typescript
|
|
385
575
|
import { Promptly, PromptlyError } from '@back23/promptly-sdk';
|
|
@@ -395,15 +585,21 @@ try {
|
|
|
395
585
|
}
|
|
396
586
|
```
|
|
397
587
|
|
|
398
|
-
|
|
588
|
+
---
|
|
589
|
+
|
|
590
|
+
## React 예시
|
|
399
591
|
|
|
400
592
|
```tsx
|
|
593
|
+
'use client';
|
|
594
|
+
|
|
401
595
|
import { useState, useEffect } from 'react';
|
|
402
596
|
import { Promptly } from '@back23/promptly-sdk';
|
|
403
597
|
|
|
598
|
+
// 싱글톤 클라이언트
|
|
404
599
|
const client = new Promptly({
|
|
405
|
-
tenantId:
|
|
600
|
+
tenantId: process.env.NEXT_PUBLIC_PROMPTLY_TENANT_ID!,
|
|
406
601
|
apiKey: process.env.NEXT_PUBLIC_PROMPTLY_API_KEY!,
|
|
602
|
+
persistToken: true,
|
|
407
603
|
});
|
|
408
604
|
|
|
409
605
|
function BlogList() {
|
|
@@ -424,8 +620,6 @@ function BlogList() {
|
|
|
424
620
|
<article key={post.id}>
|
|
425
621
|
<h2>{post.title}</h2>
|
|
426
622
|
<p>{post.excerpt}</p>
|
|
427
|
-
<span>{post.category}</span>
|
|
428
|
-
{post.tags.map(tag => <span key={tag}>{tag}</span>)}
|
|
429
623
|
</article>
|
|
430
624
|
))}
|
|
431
625
|
</div>
|
|
@@ -433,25 +627,41 @@ function BlogList() {
|
|
|
433
627
|
}
|
|
434
628
|
```
|
|
435
629
|
|
|
630
|
+
---
|
|
631
|
+
|
|
436
632
|
## Changelog
|
|
437
633
|
|
|
634
|
+
### v2.18.0
|
|
635
|
+
- 상품 리뷰 API 추가
|
|
636
|
+
- 배송 설정 API 추가
|
|
637
|
+
|
|
638
|
+
### v2.15.0
|
|
639
|
+
- 토스페이먼츠 결제 API 추가
|
|
640
|
+
|
|
438
641
|
### v2.12.0
|
|
439
|
-
-
|
|
440
|
-
-
|
|
642
|
+
- 블로그 카테고리/태그 필터 추가
|
|
643
|
+
- `category`, `tags`, `views`, `published_at` 필드 추가
|
|
644
|
+
|
|
645
|
+
### v2.10.0
|
|
646
|
+
- `persistToken` 옵션 추가 (토큰 자동 저장)
|
|
647
|
+
- `onAuthStateChange` 콜백 추가
|
|
648
|
+
- `storageType` 옵션 추가
|
|
441
649
|
|
|
442
650
|
### v2.5.0
|
|
443
|
-
-
|
|
651
|
+
- 게시판 비밀글 지원 (`is_secret`, `is_mine`)
|
|
444
652
|
|
|
445
653
|
### v2.3.0
|
|
446
|
-
-
|
|
654
|
+
- 다형성 댓글 API (board, blog, standalone)
|
|
447
655
|
|
|
448
656
|
### v2.0.0
|
|
449
|
-
- **Breaking:** API key
|
|
657
|
+
- **Breaking:** API key 필수
|
|
450
658
|
|
|
451
659
|
### v1.3.0
|
|
452
|
-
-
|
|
453
|
-
-
|
|
660
|
+
- `ListResponse<T>` 통일
|
|
661
|
+
- 예약 시스템 지원
|
|
662
|
+
|
|
663
|
+
---
|
|
454
664
|
|
|
455
|
-
##
|
|
665
|
+
## 라이선스
|
|
456
666
|
|
|
457
667
|
MIT
|