@diffsome/sdk 3.0.0 → 3.2.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 CHANGED
@@ -1,70 +1,69 @@
1
1
  # @diffsome/sdk
2
2
 
3
- Diffsome 공식 SDK - 헤드리스 CMS + 이커머스 + AI 기능을 제공합니다.
3
+ Diffsome Official SDK - Headless CMS + E-commerce + AI platform.
4
4
 
5
- **버전: 2.18.0**
5
+ **Version: 3.2.0**
6
6
 
7
- ## 설치
7
+ ## Installation
8
8
 
9
9
  ```bash
10
10
  npm install @diffsome/sdk
11
11
  ```
12
12
 
13
- ## 빠른 시작
13
+ ## Quick Start
14
14
 
15
15
  ```typescript
16
16
  import { Diffsome } from '@diffsome/sdk';
17
17
 
18
18
  const client = new Diffsome({
19
19
  tenantId: 'your-tenant-id',
20
- apiKey: 'pky_xxxxxxxxxxxxxxxx', // 필수 - Dashboard > Settings > API Tokens
21
- baseUrl: 'https://diffsome.com', // 선택
20
+ apiKey: 'pky_xxxxxxxxxxxxxxxx', // Required - Dashboard > Settings > API Tokens
21
+ baseUrl: 'https://diffsome.com', // Optional
22
22
 
23
- // 토큰 자동 저장 (로그인 유지)
23
+ // Token auto-save (persistent login)
24
24
  persistToken: true,
25
- storageType: 'localStorage', // 또는 'sessionStorage'
25
+ storageType: 'localStorage', // or 'sessionStorage'
26
26
  onAuthStateChange: (token, user) => {
27
27
  console.log('Auth changed:', user);
28
28
  },
29
29
  });
30
30
 
31
- // 블로그 조회
31
+ // Blog posts
32
32
  const { data: posts } = await client.blog.list();
33
33
 
34
- // 상품 조회
34
+ // Products
35
35
  const { data: products } = await client.shop.listProducts();
36
36
  ```
37
37
 
38
38
  ---
39
39
 
40
- ## 인증 (Auth)
40
+ ## Authentication (Auth)
41
41
 
42
- ### 기본 설정
42
+ ### Basic Setup
43
43
 
44
44
  ```typescript
45
45
  const client = new Diffsome({
46
46
  tenantId: 'demo',
47
- apiKey: 'pky_xxxxxxxxxxxxxxxx', // 필수
48
- persistToken: true, // 토큰 자동 저장
47
+ apiKey: 'pky_xxxxxxxxxxxxxxxx', // Required
48
+ persistToken: true, // Auto-save token
49
49
  });
50
50
  ```
51
51
 
52
- ### 토큰 자동 저장
52
+ ### Token Persistence
53
53
 
54
- `persistToken: true` 설정 시:
55
- - **로그인**: `localStorage`에 자동 저장
56
- - **새로고침**: 토큰 자동 복원
57
- - **로그아웃**: 토큰 자동 삭제
58
- - **저장 키**: `promptly_auth_token_{tenantId}`
54
+ With `persistToken: true`:
55
+ - **Login**: Auto-saved to `localStorage`
56
+ - **Refresh**: Token auto-restored
57
+ - **Logout**: Token auto-removed
58
+ - **Storage key**: `diffsome_auth_token_{tenantId}`
59
59
 
60
60
  ```typescript
61
61
  const client = new Diffsome({
62
62
  tenantId: 'demo',
63
63
  apiKey: 'pky_xxx',
64
64
  persistToken: true,
65
- storageType: 'localStorage', // 기본값, 또는 'sessionStorage'
65
+ storageType: 'localStorage', // Default, or 'sessionStorage'
66
66
  onAuthStateChange: (token, user) => {
67
- // 로그인/로그아웃 시 호출
68
67
  if (token) {
69
68
  console.log('Logged in:', user);
70
69
  } else {
@@ -74,10 +73,10 @@ const client = new Diffsome({
74
73
  });
75
74
  ```
76
75
 
77
- ### 로그인/회원가입
76
+ ### Login / Register
78
77
 
79
78
  ```typescript
80
- // 회원가입
79
+ // Register
81
80
  await client.auth.register({
82
81
  name: 'John Doe',
83
82
  email: 'john@example.com',
@@ -85,47 +84,47 @@ await client.auth.register({
85
84
  password_confirmation: 'password',
86
85
  });
87
86
 
88
- // 로그인 (토큰 자동 저장됨)
87
+ // Login (token auto-saved)
89
88
  const { member, token } = await client.auth.login({
90
89
  email: 'john@example.com',
91
90
  password: 'password',
92
91
  });
93
92
 
94
- // 로그아웃 (토큰 자동 삭제됨)
93
+ // Logout (token auto-removed)
95
94
  await client.auth.logout();
96
95
 
97
- // 인증 상태 확인
96
+ // Check auth status
98
97
  client.auth.isAuthenticated(); // true/false
99
98
 
100
- // 현재 사용자
99
+ // Current user
101
100
  const me = await client.auth.me();
102
101
 
103
- // 프로필 수정
102
+ // Update profile
104
103
  await client.auth.updateProfile({ name: 'New Name' });
105
104
  ```
106
105
 
107
- ### 소셜 로그인
106
+ ### Social Login
108
107
 
109
108
  ```typescript
110
- // 사용 가능한 프로바이더
109
+ // Available providers
111
110
  const providers = await client.auth.getSocialProviders();
112
111
  // ['google', 'kakao', 'naver']
113
112
 
114
- // 로그인 URL 획득
113
+ // Get login URL
115
114
  const { url } = await client.auth.getSocialAuthUrl('google');
116
115
  window.location.href = url;
117
116
 
118
- // 콜백 처리 (리다이렉트 )
117
+ // Handle callback (after redirect)
119
118
  const { member, token } = await client.auth.socialCallback('google', code);
120
119
  ```
121
120
 
122
- ### 비밀번호 재설정
121
+ ### Password Reset
123
122
 
124
123
  ```typescript
125
- // 재설정 이메일 발송
124
+ // Send reset email
126
125
  await client.auth.forgotPassword({ email: 'john@example.com' });
127
126
 
128
- // 비밀번호 재설정
127
+ // Reset password
129
128
  await client.auth.resetPassword({
130
129
  token: 'reset-token',
131
130
  email: 'john@example.com',
@@ -139,7 +138,7 @@ await client.auth.resetPassword({
139
138
  ## Blog API
140
139
 
141
140
  ```typescript
142
- // 목록 조회
141
+ // List posts
143
142
  const { data, meta } = await client.blog.list({
144
143
  page: 1,
145
144
  per_page: 10,
@@ -148,17 +147,17 @@ const { data, meta } = await client.blog.list({
148
147
  search: 'keyword',
149
148
  });
150
149
 
151
- // 상세 조회
150
+ // Get post by slug
152
151
  const post = await client.blog.get('post-slug');
153
152
 
154
- // 추천
153
+ // Featured posts
155
154
  const featured = await client.blog.featured(5);
156
155
 
157
- // 카테고리/태그별 필터
156
+ // Filter by category/tag
158
157
  const { data } = await client.blog.byCategory('news');
159
158
  const { data } = await client.blog.byTag('featured');
160
159
 
161
- // 카테고리/태그 목록
160
+ // Get categories/tags
162
161
  const categories = await client.blog.categories(); // string[]
163
162
  const tags = await client.blog.tags(); // string[]
164
163
  ```
@@ -168,23 +167,23 @@ const tags = await client.blog.tags(); // string[]
168
167
  ## Boards API
169
168
 
170
169
  ```typescript
171
- // 게시판 목록
170
+ // List boards
172
171
  const { data: boards } = await client.boards.list();
173
172
 
174
- // 게시판 조회
173
+ // Get board
175
174
  const board = await client.boards.get('board-slug');
176
175
 
177
- // 게시글 목록
176
+ // List posts
178
177
  const { data: posts } = await client.boards.listPosts('board-slug', {
179
178
  page: 1,
180
179
  per_page: 10,
181
180
  search: 'keyword',
182
181
  });
183
182
 
184
- // 게시글 상세
183
+ // Get post
185
184
  const post = await client.boards.getPost(postId);
186
185
 
187
- // 게시글 작성 (인증 필요)
186
+ // Create post (auth required)
188
187
  await client.boards.createPost({
189
188
  board_id: 1,
190
189
  title: 'Title',
@@ -192,7 +191,7 @@ await client.boards.createPost({
192
191
  is_secret: false,
193
192
  });
194
193
 
195
- // 게시글 수정/삭제
194
+ // Update/Delete post
196
195
  await client.boards.updatePost(postId, { title: 'New Title' });
197
196
  await client.boards.deletePost(postId);
198
197
  ```
@@ -201,31 +200,31 @@ await client.boards.deletePost(postId);
201
200
 
202
201
  ## Comments API
203
202
 
204
- 게시판, 블로그, 독립 댓글(방명록) 지원
203
+ Supports board posts, blog posts, and standalone pages (guestbook).
205
204
 
206
205
  ```typescript
207
- // 게시판 댓글
206
+ // Board post comments
208
207
  const { data } = await client.comments.boardPost(postId);
209
208
  await client.comments.createBoardPost(postId, {
210
209
  author_name: 'John',
211
210
  content: 'Great!',
212
- password: '1234', // 비회원 댓글
211
+ password: '1234', // Guest comment
213
212
  });
214
213
 
215
- // 블로그 댓글
214
+ // Blog post comments
216
215
  const { data } = await client.comments.blogPost('post-slug');
217
216
  await client.comments.createBlogPost('post-slug', {
218
217
  content: 'Nice article!',
219
218
  });
220
219
 
221
- // 독립 댓글 (방명록)
220
+ // Standalone comments (guestbook)
222
221
  const { data } = await client.comments.standalone('guestbook');
223
222
  await client.comments.createStandalone('guestbook', {
224
223
  author_name: 'Visitor',
225
224
  content: 'Hello!',
226
225
  });
227
226
 
228
- // 공통
227
+ // Common operations
229
228
  await client.comments.update(commentId, { content: 'Updated' });
230
229
  await client.comments.delete(commentId, { password: '1234' });
231
230
  await client.comments.like(commentId);
@@ -235,10 +234,10 @@ await client.comments.like(commentId);
235
234
 
236
235
  ## Shop API
237
236
 
238
- ### 상품
237
+ ### Products
239
238
 
240
239
  ```typescript
241
- // 상품 목록
240
+ // List products
242
241
  const { data: products } = await client.shop.listProducts({
243
242
  category: 'shoes',
244
243
  is_featured: true,
@@ -247,75 +246,126 @@ const { data: products } = await client.shop.listProducts({
247
246
  search: 'keyword',
248
247
  });
249
248
 
250
- // 상품 상세
249
+ // Get product by slug
251
250
  const product = await client.shop.getProduct('product-slug');
252
251
 
253
- // 추천 상품
252
+ // Featured products
254
253
  const featured = await client.shop.featuredProducts(8);
255
254
 
256
- // 카테고리 목록
257
- const categories = await client.shop.listCategories();
255
+ // Categories
256
+ const { data: categories } = await client.shop.listCategories();
258
257
  ```
259
258
 
260
- ### 상품 리뷰
259
+ ### Product Types
261
260
 
262
261
  ```typescript
263
- // 리뷰 목록
262
+ // Filter by product type
263
+ const { data } = await client.shop.listProductsByType('digital');
264
+ const { data } = await client.shop.getDigitalProducts();
265
+ const { data } = await client.shop.getSubscriptionProducts();
266
+ const { data } = await client.shop.getBundleProducts();
267
+ ```
268
+
269
+ ### Product Reviews
270
+
271
+ ```typescript
272
+ // List reviews
264
273
  const { data: reviews, stats } = await client.shop.getProductReviews('product-slug', {
265
274
  page: 1,
266
275
  per_page: 10,
267
- rating: 5, // 별점 필터
276
+ rating: 5, // Filter by rating
268
277
  });
269
278
 
270
- // 리뷰 통계
279
+ // Review stats
271
280
  // stats = { average_rating: 4.5, total_count: 123, rating_counts: { 5: 80, 4: 30, ... } }
272
281
 
273
- // 리뷰 작성 (인증 + 구매 필요)
274
- await client.shop.createProductReview('product-slug', {
282
+ // Create review (auth + purchase required)
283
+ await client.shop.createReview('product-slug', {
275
284
  rating: 5,
276
285
  title: 'Great product!',
277
286
  content: 'Highly recommended.',
278
287
  images: ['https://...'],
279
288
  });
280
289
 
281
- // 리뷰 수정/삭제
282
- await client.shop.updateProductReview(reviewId, { rating: 4 });
283
- await client.shop.deleteProductReview(reviewId);
290
+ // Check if can review
291
+ const { can_review, reason } = await client.shop.canReviewProduct('product-slug');
284
292
 
285
- // 도움이 됐어요
293
+ // Update/Delete review
294
+ await client.shop.updateReview(reviewId, { rating: 4 });
295
+ await client.shop.deleteReview(reviewId);
296
+
297
+ // Mark as helpful
286
298
  await client.shop.markReviewHelpful(reviewId);
287
299
 
288
- // 리뷰 목록
289
- const { data: myReviews } = await client.shop.getMyReviews();
300
+ // My reviews
301
+ const { data: myReviews } = await client.shop.myReviews();
290
302
  ```
291
303
 
292
- ### 장바구니 (인증 필요)
304
+ ### Cart
305
+
306
+ Works for both authenticated users and guests. Guest carts use session ID persistence.
293
307
 
294
308
  ```typescript
295
- // 장바구니 조회
309
+ // Get cart
296
310
  const cart = await client.shop.getCart();
297
311
 
298
- // 상품 추가
312
+ // Add item
299
313
  await client.shop.addToCart({
300
314
  product_id: 1,
301
315
  quantity: 2,
302
- variant_id: 3, // 옵션 상품
316
+ variant_id: 3, // Variant option
303
317
  });
304
318
 
305
- // 수량 변경
319
+ // Update quantity
306
320
  await client.shop.updateCartItem(itemId, { quantity: 3 });
307
321
 
308
- // 상품 제거
322
+ // Remove item
309
323
  await client.shop.removeFromCart(itemId);
310
324
 
311
- // 장바구니 비우기
325
+ // Clear cart
312
326
  await client.shop.clearCart();
313
327
  ```
314
328
 
315
- ### 주문 (인증 필요)
329
+ ### Wishlist (Auth Required)
316
330
 
317
331
  ```typescript
318
- // 주문 생성
332
+ // Get wishlist
333
+ const { data: items } = await client.shop.getWishlist();
334
+
335
+ // Add to wishlist
336
+ await client.shop.addToWishlist({
337
+ product_id: 1,
338
+ variant_id: 2,
339
+ note: 'Birthday gift',
340
+ });
341
+
342
+ // Toggle wishlist (add if not in, remove if in)
343
+ const { action, in_wishlist } = await client.shop.toggleWishlist(productId);
344
+
345
+ // Check if in wishlist
346
+ const isInWishlist = await client.shop.isInWishlist(productId);
347
+
348
+ // Bulk check (for product list pages)
349
+ const wishlistStatus = await client.shop.checkWishlistBulk([1, 2, 3]);
350
+ // { '1': true, '2': false, '3': true }
351
+
352
+ // Wishlist count
353
+ const count = await client.shop.getWishlistCount();
354
+
355
+ // Move to cart
356
+ const { moved, failed, moved_count } = await client.shop.moveWishlistToCart();
357
+
358
+ // Update note
359
+ await client.shop.updateWishlistNote(wishlistId, 'New note');
360
+
361
+ // Remove from wishlist
362
+ await client.shop.removeFromWishlist(wishlistId);
363
+ ```
364
+
365
+ ### Orders (Auth Required)
366
+
367
+ ```typescript
368
+ // Create order
319
369
  const order = await client.shop.createOrder({
320
370
  orderer_name: 'John Doe',
321
371
  orderer_email: 'john@example.com',
@@ -323,76 +373,173 @@ const order = await client.shop.createOrder({
323
373
  shipping_name: 'John Doe',
324
374
  shipping_phone: '010-1234-5678',
325
375
  shipping_zipcode: '12345',
326
- shipping_address: '서울시 강남구',
327
- shipping_address_detail: '101동 101',
328
- shipping_memo: '부재시 경비실',
376
+ shipping_address: 'Seoul, Gangnam',
377
+ shipping_address_detail: 'Apt 101',
378
+ shipping_memo: 'Leave at door',
329
379
  coupon_code: 'SAVE10',
330
380
  });
331
381
 
332
- // 주문 목록
382
+ // List orders
333
383
  const { data: orders } = await client.shop.listOrders();
334
384
 
335
- // 주문 상세
385
+ // Get order
336
386
  const orderDetail = await client.shop.getOrder(orderId);
337
387
 
338
- // 주문 취소
388
+ // Cancel order
339
389
  await client.shop.cancelOrder(orderId);
340
390
  ```
341
391
 
342
- ### 결제 (토스페이먼츠)
392
+ ### Payments - Toss Payments
343
393
 
344
394
  ```typescript
345
- // 결제 준비
346
- const payment = await client.shop.preparePayment({
395
+ // Prepare payment
396
+ const payment = await client.shop.tossPaymentReady({
347
397
  order_number: 'ORD-123',
348
398
  success_url: 'https://mysite.com/payment/success',
349
399
  fail_url: 'https://mysite.com/payment/fail',
350
400
  });
351
- // payment = { client_key, order_id, order_name, amount, customer_name, ... }
401
+ // { client_key, order_id, order_name, amount, customer_name, ... }
352
402
 
353
- // 결제 승인 (토스 결제 완료 후)
354
- await client.shop.confirmPayment({
403
+ // Confirm payment (after Toss redirect)
404
+ const result = await client.shop.tossPaymentConfirm({
355
405
  payment_key: 'toss_payment_key',
356
406
  order_id: 'ORD-123',
357
407
  amount: 50000,
358
408
  });
409
+
410
+ // Cancel payment
411
+ await client.shop.tossPaymentCancel('ORD-123', 'Customer request', 50000);
359
412
  ```
360
413
 
361
- ### 쿠폰
414
+ ### Payments - Stripe
362
415
 
363
416
  ```typescript
364
- // 쿠폰 검증
417
+ // Create Checkout Session
418
+ const { session_id, checkout_url } = await client.shop.stripeCheckout({
419
+ order_number: 'ORD-123',
420
+ success_url: 'https://mysite.com/payment/success',
421
+ cancel_url: 'https://mysite.com/payment/cancel',
422
+ });
423
+
424
+ // Redirect to Stripe
425
+ window.location.href = checkout_url;
426
+
427
+ // Verify payment (after Stripe redirect)
428
+ const result = await client.shop.stripeVerify({
429
+ session_id: 'cs_xxx',
430
+ });
431
+
432
+ // Refund
433
+ await client.shop.stripeRefund('ORD-123', 'Customer request', 50000);
434
+ ```
435
+
436
+ ### Payment Status
437
+
438
+ ```typescript
439
+ // Check available payment methods
440
+ const status = await client.shop.getPaymentStatus();
441
+ // {
442
+ // toss: { available: true },
443
+ // stripe: { available: true, publishable_key: 'pk_xxx' }
444
+ // }
445
+ ```
446
+
447
+ ### Coupons
448
+
449
+ ```typescript
450
+ // Validate coupon
365
451
  const result = await client.shop.validateCoupon('SAVE10', 50000);
366
452
  // { valid: true, discount_amount: 5000, coupon: { ... } }
367
453
 
368
- // 쿠폰 목록
454
+ // My coupons
369
455
  const coupons = await client.shop.myCoupons();
370
456
  ```
371
457
 
372
- ### 배송 설정
458
+ ### Digital Downloads (Auth Required)
459
+
460
+ ```typescript
461
+ // Get all my downloads
462
+ const downloads = await client.shop.getMyDownloads();
463
+
464
+ // Get downloads for specific order
465
+ const orderDownloads = await client.shop.getOrderDownloads('ORD-123');
466
+
467
+ // Get download URL
468
+ const downloadUrl = await client.shop.downloadFile(token);
469
+
470
+ // Get download info without downloading
471
+ const info = await client.shop.getDownloadInfo(token);
472
+ // {
473
+ // id, token, file: { name, file_size_human, extension },
474
+ // download_count, download_limit, remaining_downloads,
475
+ // can_download, blocked_reason, expires_at
476
+ // }
477
+ ```
478
+
479
+ ### Subscriptions (Auth Required)
480
+
481
+ ```typescript
482
+ // Get my subscriptions
483
+ const subscriptions = await client.shop.getSubscriptions();
484
+
485
+ // Get subscription detail
486
+ const subscription = await client.shop.getSubscription(id);
487
+ // {
488
+ // id, product, plan: { interval, price, trial_days, features },
489
+ // status, is_active, on_trial, current_period_end, ...
490
+ // }
491
+
492
+ // Create subscription (requires Stripe payment method)
493
+ const { subscription, client_secret } = await client.shop.createSubscription({
494
+ plan_id: 1,
495
+ payment_method_id: 'pm_xxx',
496
+ });
497
+
498
+ // Create setup intent for adding payment method
499
+ const { client_secret } = await client.shop.createSetupIntent();
500
+
501
+ // Cancel subscription
502
+ await client.shop.cancelSubscription(id); // At end of period
503
+ await client.shop.cancelSubscription(id, true); // Immediately
504
+
505
+ // Pause/Resume subscription
506
+ await client.shop.pauseSubscription(id);
507
+ await client.shop.resumeSubscription(id);
508
+ ```
509
+
510
+ ### Bundle Products
373
511
 
374
512
  ```typescript
375
- const settings = await client.shop.getShippingSettings();
376
- // { base_fee, free_shipping_threshold, ... }
513
+ // Get bundle items and pricing
514
+ const bundle = await client.shop.getBundleItems('product-slug');
515
+ // {
516
+ // items: [{ product_id, name, quantity, unit_price, subtotal }],
517
+ // original_total: 100000,
518
+ // discount_type: 'percent',
519
+ // discount_value: 20,
520
+ // discount_amount: 20000,
521
+ // final_price: 80000,
522
+ // savings_percent: 20
523
+ // }
377
524
  ```
378
525
 
379
526
  ---
380
527
 
381
528
  ## Reservation API
382
529
 
383
- ### 공개 API
530
+ ### Public API
384
531
 
385
532
  ```typescript
386
- // 예약 설정
533
+ // Reservation settings
387
534
  const settings = await client.reservation.getSettings();
388
535
 
389
- // 서비스 목록
536
+ // Services list
390
537
  const services = await client.reservation.listServices();
391
538
 
392
- // 담당자 목록
539
+ // Staff list
393
540
  const staff = await client.reservation.listStaff(serviceId);
394
541
 
395
- // 예약 가능 날짜
542
+ // Available dates
396
543
  const dates = await client.reservation.getAvailableDates({
397
544
  service_id: 1,
398
545
  staff_id: 2,
@@ -400,7 +547,7 @@ const dates = await client.reservation.getAvailableDates({
400
547
  end_date: '2026-01-31',
401
548
  });
402
549
 
403
- // 예약 가능 시간
550
+ // Available time slots
404
551
  const slots = await client.reservation.getAvailableSlots({
405
552
  service_id: 1,
406
553
  date: '2026-01-15',
@@ -408,10 +555,10 @@ const slots = await client.reservation.getAvailableSlots({
408
555
  });
409
556
  ```
410
557
 
411
- ### 예약 관리 (인증 필요)
558
+ ### Reservation Management (Auth Required)
412
559
 
413
560
  ```typescript
414
- // 예약 생성
561
+ // Create reservation
415
562
  await client.reservation.create({
416
563
  service_id: 1,
417
564
  staff_id: 2,
@@ -420,18 +567,18 @@ await client.reservation.create({
420
567
  customer_name: 'John Doe',
421
568
  customer_phone: '010-1234-5678',
422
569
  customer_email: 'john@example.com',
423
- notes: '요청사항',
570
+ notes: 'Special request',
424
571
  });
425
572
 
426
- // 예약 목록
573
+ // My reservations
427
574
  const { data } = await client.reservation.list({ status: 'confirmed' });
428
575
 
429
- // 다가오는/지난 예약
576
+ // Upcoming/Past reservations
430
577
  const upcoming = await client.reservation.upcoming(5);
431
578
  const past = await client.reservation.past(10);
432
579
 
433
- // 예약 취소
434
- await client.reservation.cancel('RES-20260115-001', '일정 변경');
580
+ // Cancel reservation
581
+ await client.reservation.cancel('RES-20260115-001', 'Schedule change');
435
582
  ```
436
583
 
437
584
  ---
@@ -439,38 +586,38 @@ await client.reservation.cancel('RES-20260115-001', '일정 변경');
439
586
  ## Forms API
440
587
 
441
588
  ```typescript
442
- // 목록
589
+ // List forms
443
590
  const { data: forms } = await client.forms.list();
444
591
 
445
- // 상세 (필드 정보 포함)
592
+ // Get form (includes field definitions)
446
593
  const form = await client.forms.get('contact');
447
594
 
448
- // 제출
595
+ // Submit form
449
596
  await client.forms.submit('contact', {
450
597
  name: 'John Doe',
451
598
  email: 'john@example.com',
452
599
  message: 'Hello!',
453
600
  });
454
601
 
455
- // 제출 목록 (인증 필요)
602
+ // My submissions (auth required)
456
603
  const { data: submissions } = await client.forms.mySubmissions();
457
604
  ```
458
605
 
459
606
  ---
460
607
 
461
- ## Media API (인증 필요)
608
+ ## Media API (Auth Required)
462
609
 
463
610
  ```typescript
464
- // 파일 업로드
611
+ // Upload file
465
612
  const media = await client.media.upload(file);
466
613
 
467
- // 여러 파일 업로드
614
+ // Upload multiple files
468
615
  const mediaList = await client.media.uploadMultiple([file1, file2]);
469
616
 
470
- // 미디어 목록
617
+ // My media list
471
618
  const { data: myMedia } = await client.media.list({ type: 'image/jpeg' });
472
619
 
473
- // 미디어 삭제
620
+ // Delete media
474
621
  await client.media.delete(mediaId);
475
622
  ```
476
623
 
@@ -478,18 +625,18 @@ await client.media.delete(mediaId);
478
625
 
479
626
  ## Custom Entities API
480
627
 
481
- 동적 데이터 구조 생성/관리
628
+ Dynamic data structure creation and management.
482
629
 
483
- ### 엔티티 정의
630
+ ### Entity Definition
484
631
 
485
632
  ```typescript
486
- // 엔티티 목록
633
+ // List entities
487
634
  const entities = await client.entities.list();
488
635
 
489
- // 엔티티 조회
636
+ // Get entity
490
637
  const entity = await client.entities.get('customers');
491
638
 
492
- // 엔티티 생성
639
+ // Create entity
493
640
  await client.entities.create({
494
641
  name: 'Customer',
495
642
  slug: 'customers',
@@ -505,36 +652,36 @@ await client.entities.create({
505
652
  },
506
653
  });
507
654
 
508
- // 엔티티 수정/삭제
655
+ // Update/Delete entity
509
656
  await client.entities.update('customers', { name: 'Clients' });
510
657
  await client.entities.delete('customers', true); // force
511
658
  ```
512
659
 
513
- ### 레코드
660
+ ### Records
514
661
 
515
662
  ```typescript
516
- // 레코드 목록
663
+ // List records
517
664
  const { data: records } = await client.entities.listRecords('customers', {
518
665
  search: 'ACME',
519
666
  filters: JSON.stringify({ status: 'active' }),
520
667
  });
521
668
 
522
- // 레코드 조회
669
+ // Get record
523
670
  const record = await client.entities.getRecord('customers', 1);
524
671
 
525
- // 레코드 생성
672
+ // Create record
526
673
  await client.entities.createRecord('customers', {
527
674
  company: 'ACME Corp',
528
675
  email: 'contact@acme.com',
529
676
  status: 'active',
530
677
  });
531
678
 
532
- // 레코드 수정/삭제
679
+ // Update/Delete record
533
680
  await client.entities.updateRecord('customers', 1, { status: 'inactive' });
534
681
  await client.entities.deleteRecord('customers', 1);
535
682
  ```
536
683
 
537
- ### TypeScript 지원
684
+ ### TypeScript Support
538
685
 
539
686
  ```typescript
540
687
  interface Customer {
@@ -549,13 +696,13 @@ const { data } = await customers.list(); // data: Customer[]
549
696
 
550
697
  ---
551
698
 
552
- ## 응답 타입
699
+ ## Response Types
553
700
 
554
- 모든 목록 API는 일관된 형식 반환:
701
+ All list APIs return consistent format:
555
702
 
556
703
  ```typescript
557
704
  interface ListResponse<T> {
558
- data: T[]; // 항상 배열, null 아님
705
+ data: T[]; // Always array, never null
559
706
  meta: {
560
707
  current_page: number;
561
708
  last_page: number;
@@ -569,15 +716,15 @@ interface ListResponse<T> {
569
716
 
570
717
  ---
571
718
 
572
- ## 에러 처리
719
+ ## Error Handling
573
720
 
574
721
  ```typescript
575
- import { Promptly, PromptlyError } from '@diffsome/sdk';
722
+ import { Diffsome, DiffsomeError } from '@diffsome/sdk';
576
723
 
577
724
  try {
578
725
  await client.auth.login({ email: 'wrong@email.com', password: 'wrong' });
579
726
  } catch (error) {
580
- if (error instanceof PromptlyError) {
727
+ if (error instanceof DiffsomeError) {
581
728
  console.log(error.message); // "Invalid credentials"
582
729
  console.log(error.status); // 401
583
730
  console.log(error.errors); // { email: ["Invalid email or password"] }
@@ -587,7 +734,7 @@ try {
587
734
 
588
735
  ---
589
736
 
590
- ## React 예시
737
+ ## React Example
591
738
 
592
739
  ```tsx
593
740
  'use client';
@@ -595,10 +742,10 @@ try {
595
742
  import { useState, useEffect } from 'react';
596
743
  import { Diffsome } from '@diffsome/sdk';
597
744
 
598
- // 싱글톤 클라이언트
745
+ // Singleton client
599
746
  const client = new Diffsome({
600
- tenantId: process.env.NEXT_PUBLIC_PROMPTLY_TENANT_ID!,
601
- apiKey: process.env.NEXT_PUBLIC_PROMPTLY_API_KEY!,
747
+ tenantId: process.env.NEXT_PUBLIC_DIFFSOME_TENANT_ID!,
748
+ apiKey: process.env.NEXT_PUBLIC_DIFFSOME_API_KEY!,
602
749
  persistToken: true,
603
750
  });
604
751
 
@@ -631,37 +778,56 @@ function BlogList() {
631
778
 
632
779
  ## Changelog
633
780
 
781
+ ### v3.2.0
782
+ - Bundle product support
783
+ - `getBundleItems()` API
784
+ - Product type filter (`listProductsByType()`)
785
+
786
+ ### v3.1.0
787
+ - Subscription management API
788
+ - `getSubscriptions()`, `createSubscription()`, `cancelSubscription()`
789
+ - `pauseSubscription()`, `resumeSubscription()`
790
+ - Stripe setup intent for payment method
791
+
792
+ ### v3.0.0
793
+ - **Breaking:** Renamed from `Promptly` to `Diffsome`
794
+ - **Breaking:** Storage key changed from `promptly_auth_token_` to `diffsome_auth_token_`
795
+ - Digital download API (`getMyDownloads()`, `downloadFile()`)
796
+ - Wishlist API (full CRUD + bulk operations)
797
+ - Guest cart with session persistence
798
+ - Stripe payment integration
799
+
634
800
  ### v2.18.0
635
- - 상품 리뷰 API 추가
636
- - 배송 설정 API 추가
801
+ - Product review API
802
+ - Shipping settings API
637
803
 
638
804
  ### v2.15.0
639
- - 토스페이먼츠 결제 API 추가
805
+ - Toss Payments integration
640
806
 
641
807
  ### v2.12.0
642
- - 블로그 카테고리/태그 필터 추가
643
- - `category`, `tags`, `views`, `published_at` 필드 추가
808
+ - Blog category/tag filters
809
+ - Added `category`, `tags`, `views`, `published_at` fields
644
810
 
645
811
  ### v2.10.0
646
- - `persistToken` 옵션 추가 (토큰 자동 저장)
647
- - `onAuthStateChange` 콜백 추가
648
- - `storageType` 옵션 추가
812
+ - `persistToken` option for auto token storage
813
+ - `onAuthStateChange` callback
814
+ - `storageType` option
649
815
 
650
816
  ### v2.5.0
651
- - 게시판 비밀글 지원 (`is_secret`, `is_mine`)
817
+ - Secret posts support (`is_secret`, `is_mine`)
652
818
 
653
819
  ### v2.3.0
654
- - 다형성 댓글 API (board, blog, standalone)
820
+ - Polymorphic comments API (board, blog, standalone)
655
821
 
656
822
  ### v2.0.0
657
- - **Breaking:** API key 필수
823
+ - **Breaking:** API key required
658
824
 
659
825
  ### v1.3.0
660
- - `ListResponse<T>` 통일
661
- - 예약 시스템 지원
826
+ - `ListResponse<T>` unified format
827
+ - Reservation system support
662
828
 
663
829
  ---
664
830
 
665
- ## 라이선스
831
+ ## License
666
832
 
667
833
  MIT