@diffsome/sdk 3.0.0 → 3.2.0
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 +322 -156
- package/dist/index.d.mts +293 -15
- package/dist/index.d.ts +293 -15
- package/dist/index.js +232 -13
- package/dist/index.mjs +232 -13
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,70 +1,69 @@
|
|
|
1
1
|
# @diffsome/sdk
|
|
2
2
|
|
|
3
|
-
Diffsome
|
|
3
|
+
Diffsome Official SDK - Headless CMS + E-commerce + AI platform.
|
|
4
4
|
|
|
5
|
-
|
|
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', //
|
|
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', //
|
|
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
|
-
##
|
|
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
|
-
-
|
|
56
|
-
-
|
|
57
|
-
-
|
|
58
|
-
-
|
|
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', //
|
|
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
|
-
//
|
|
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.
|
|
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.
|
|
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.
|
|
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: '
|
|
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.
|
|
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
|
-
//
|
|
401
|
+
// { client_key, order_id, order_name, amount, customer_name, ... }
|
|
352
402
|
|
|
353
|
-
//
|
|
354
|
-
await client.shop.
|
|
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
|
-
|
|
376
|
-
|
|
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
|
-
###
|
|
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
|
-
|
|
701
|
+
All list APIs return consistent format:
|
|
555
702
|
|
|
556
703
|
```typescript
|
|
557
704
|
interface ListResponse<T> {
|
|
558
|
-
data: T[]; //
|
|
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 {
|
|
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
|
|
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.
|
|
601
|
-
apiKey: process.env.
|
|
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
|
-
-
|
|
636
|
-
-
|
|
801
|
+
- Product review API
|
|
802
|
+
- Shipping settings API
|
|
637
803
|
|
|
638
804
|
### v2.15.0
|
|
639
|
-
-
|
|
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
|
-
-
|
|
817
|
+
- Secret posts support (`is_secret`, `is_mine`)
|
|
652
818
|
|
|
653
819
|
### v2.3.0
|
|
654
|
-
-
|
|
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
|