perspectapi-ts-sdk 2.7.0 → 2.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +352 -2
- package/dist/index.d.ts +352 -2
- package/dist/index.js +328 -1
- package/dist/index.mjs +327 -1
- package/package.json +1 -1
- package/src/client/products-client.ts +123 -0
- package/src/client/site-users-client.ts +352 -0
- package/src/index.ts +10 -0
- package/src/perspect-api-client.ts +3 -0
- package/src/types/index.ts +90 -1
- package/src/utils/validators.ts +1 -2
package/dist/index.mjs
CHANGED
|
@@ -707,7 +707,7 @@ var AuthClient = class extends BaseClient {
|
|
|
707
707
|
|
|
708
708
|
// src/utils/validators.ts
|
|
709
709
|
var MAX_API_QUERY_LIMIT = 100;
|
|
710
|
-
var ALLOWED_CONTENT_TYPES = ["post", "page"];
|
|
710
|
+
var ALLOWED_CONTENT_TYPES = ["post", "page", "block"];
|
|
711
711
|
function validateLimit(limit, context) {
|
|
712
712
|
if (typeof limit !== "number" || Number.isNaN(limit) || !Number.isFinite(limit)) {
|
|
713
713
|
throw new Error(`[PerspectAPI] ${context} limit must be a finite number.`);
|
|
@@ -1461,6 +1461,64 @@ var ProductsClient = class extends BaseClient {
|
|
|
1461
1461
|
}
|
|
1462
1462
|
return void 0;
|
|
1463
1463
|
}
|
|
1464
|
+
// ============================================================================
|
|
1465
|
+
// PRODUCT OPTIONS AND SKUS (for variants)
|
|
1466
|
+
// ============================================================================
|
|
1467
|
+
/**
|
|
1468
|
+
* Get all options (and their values) for a product
|
|
1469
|
+
*/
|
|
1470
|
+
async getProductOptions(siteName, productId) {
|
|
1471
|
+
const endpoint = this.siteScopedEndpoint(
|
|
1472
|
+
siteName,
|
|
1473
|
+
`/products/${productId}/options`,
|
|
1474
|
+
{ includeSitesSegment: false }
|
|
1475
|
+
);
|
|
1476
|
+
return this.getSingle(endpoint);
|
|
1477
|
+
}
|
|
1478
|
+
/**
|
|
1479
|
+
* Create a new product option (e.g., "Size", "Color")
|
|
1480
|
+
*/
|
|
1481
|
+
async createProductOption(siteName, productId, data) {
|
|
1482
|
+
const endpoint = this.siteScopedEndpoint(
|
|
1483
|
+
siteName,
|
|
1484
|
+
`/products/${productId}/options`,
|
|
1485
|
+
{ includeSitesSegment: false }
|
|
1486
|
+
);
|
|
1487
|
+
return this.create(endpoint, data);
|
|
1488
|
+
}
|
|
1489
|
+
/**
|
|
1490
|
+
* Create a new value for a product option (e.g., "Small", "Red")
|
|
1491
|
+
*/
|
|
1492
|
+
async createProductOptionValue(siteName, productId, optionId, data) {
|
|
1493
|
+
const endpoint = this.siteScopedEndpoint(
|
|
1494
|
+
siteName,
|
|
1495
|
+
`/products/${productId}/options/${optionId}/values`,
|
|
1496
|
+
{ includeSitesSegment: false }
|
|
1497
|
+
);
|
|
1498
|
+
return this.create(endpoint, data);
|
|
1499
|
+
}
|
|
1500
|
+
/**
|
|
1501
|
+
* Get all SKUs for a product (with their option value combinations)
|
|
1502
|
+
*/
|
|
1503
|
+
async getProductSkus(siteName, productId) {
|
|
1504
|
+
const endpoint = this.siteScopedEndpoint(
|
|
1505
|
+
siteName,
|
|
1506
|
+
`/products/${productId}/skus`,
|
|
1507
|
+
{ includeSitesSegment: false }
|
|
1508
|
+
);
|
|
1509
|
+
return this.getSingle(endpoint);
|
|
1510
|
+
}
|
|
1511
|
+
/**
|
|
1512
|
+
* Create or update a SKU for a product variant combination
|
|
1513
|
+
*/
|
|
1514
|
+
async createProductSku(siteName, productId, data) {
|
|
1515
|
+
const endpoint = this.siteScopedEndpoint(
|
|
1516
|
+
siteName,
|
|
1517
|
+
`/products/${productId}/skus`,
|
|
1518
|
+
{ includeSitesSegment: false }
|
|
1519
|
+
);
|
|
1520
|
+
return this.create(endpoint, data);
|
|
1521
|
+
}
|
|
1464
1522
|
};
|
|
1465
1523
|
|
|
1466
1524
|
// src/client/categories-client.ts
|
|
@@ -2175,6 +2233,271 @@ var NewsletterClient = class extends BaseClient {
|
|
|
2175
2233
|
}
|
|
2176
2234
|
};
|
|
2177
2235
|
|
|
2236
|
+
// src/client/site-users-client.ts
|
|
2237
|
+
var SiteUsersClient = class extends BaseClient {
|
|
2238
|
+
constructor(http, cache) {
|
|
2239
|
+
super(http, "/api/v1", cache);
|
|
2240
|
+
}
|
|
2241
|
+
/**
|
|
2242
|
+
* Build a site user endpoint scoped to a site (without /sites prefix)
|
|
2243
|
+
*/
|
|
2244
|
+
siteUserEndpoint(siteName, endpoint) {
|
|
2245
|
+
return this.siteScopedEndpoint(siteName, endpoint, { includeSitesSegment: false });
|
|
2246
|
+
}
|
|
2247
|
+
// ============================================================================
|
|
2248
|
+
// PUBLIC ENDPOINTS (OTP authentication)
|
|
2249
|
+
// ============================================================================
|
|
2250
|
+
/**
|
|
2251
|
+
* Request OTP for login/signup
|
|
2252
|
+
* @param siteName - The site name
|
|
2253
|
+
* @param data - Email address
|
|
2254
|
+
* @param csrfToken - CSRF token (required for browser-based submissions)
|
|
2255
|
+
*/
|
|
2256
|
+
async requestOtp(siteName, data, csrfToken) {
|
|
2257
|
+
if (typeof window !== "undefined" && !csrfToken) {
|
|
2258
|
+
console.warn("CSRF token recommended for browser-based OTP requests");
|
|
2259
|
+
}
|
|
2260
|
+
return this.create(
|
|
2261
|
+
this.siteUserEndpoint(siteName, "/users/request-otp"),
|
|
2262
|
+
data,
|
|
2263
|
+
csrfToken
|
|
2264
|
+
);
|
|
2265
|
+
}
|
|
2266
|
+
/**
|
|
2267
|
+
* Verify OTP and get JWT token
|
|
2268
|
+
*
|
|
2269
|
+
* For cross-domain authentication, you must manually set the token after verification:
|
|
2270
|
+
* ```typescript
|
|
2271
|
+
* const response = await client.siteUsers.verifyOtp('mysite', { email, code });
|
|
2272
|
+
* const { token, user } = response.data;
|
|
2273
|
+
*
|
|
2274
|
+
* // Store token securely (choose one):
|
|
2275
|
+
* // Option 1: Memory (lost on refresh, most secure)
|
|
2276
|
+
* client.setAuth(token);
|
|
2277
|
+
*
|
|
2278
|
+
* // Option 2: httpOnly cookie on YOUR domain (recommended for production)
|
|
2279
|
+
* await fetch('/your-api/set-auth-cookie', {
|
|
2280
|
+
* method: 'POST',
|
|
2281
|
+
* body: JSON.stringify({ token })
|
|
2282
|
+
* });
|
|
2283
|
+
* client.setAuth(token);
|
|
2284
|
+
*
|
|
2285
|
+
* // Option 3: localStorage (vulnerable to XSS, not recommended)
|
|
2286
|
+
* localStorage.setItem('site_user_token', token);
|
|
2287
|
+
* client.setAuth(token);
|
|
2288
|
+
* ```
|
|
2289
|
+
*
|
|
2290
|
+
* For convenience, use `verifyOtpAndSetAuth()` to automatically set the token in memory.
|
|
2291
|
+
*
|
|
2292
|
+
* @param siteName - The site name
|
|
2293
|
+
* @param data - Email and code
|
|
2294
|
+
* @param csrfToken - CSRF token (required for browser-based submissions)
|
|
2295
|
+
*/
|
|
2296
|
+
async verifyOtp(siteName, data, csrfToken) {
|
|
2297
|
+
if (typeof window !== "undefined" && !csrfToken) {
|
|
2298
|
+
console.warn("CSRF token recommended for browser-based OTP verification");
|
|
2299
|
+
}
|
|
2300
|
+
return this.create(
|
|
2301
|
+
this.siteUserEndpoint(siteName, "/users/verify-otp"),
|
|
2302
|
+
data,
|
|
2303
|
+
csrfToken
|
|
2304
|
+
);
|
|
2305
|
+
}
|
|
2306
|
+
/**
|
|
2307
|
+
* Verify OTP and automatically set the token for subsequent requests
|
|
2308
|
+
*
|
|
2309
|
+
* Convenience method that:
|
|
2310
|
+
* 1. Verifies the OTP
|
|
2311
|
+
* 2. Automatically calls setAuth() with the returned token
|
|
2312
|
+
*
|
|
2313
|
+
* Note: Token is stored in memory only and will be lost on page refresh.
|
|
2314
|
+
* For persistent auth, use verifyOtp() and store the token yourself.
|
|
2315
|
+
*
|
|
2316
|
+
* @param siteName - The site name
|
|
2317
|
+
* @param data - Email and code
|
|
2318
|
+
* @param csrfToken - CSRF token (required for browser-based submissions)
|
|
2319
|
+
*/
|
|
2320
|
+
async verifyOtpAndSetAuth(siteName, data, csrfToken) {
|
|
2321
|
+
const response = await this.verifyOtp(siteName, data, csrfToken);
|
|
2322
|
+
if (response.data?.token) {
|
|
2323
|
+
this.http.setAuth(response.data.token);
|
|
2324
|
+
}
|
|
2325
|
+
return response;
|
|
2326
|
+
}
|
|
2327
|
+
/**
|
|
2328
|
+
* Logout (clear session cookie)
|
|
2329
|
+
* @param siteName - The site name
|
|
2330
|
+
*/
|
|
2331
|
+
async logout(siteName) {
|
|
2332
|
+
return this.create(
|
|
2333
|
+
this.siteUserEndpoint(siteName, "/users/logout"),
|
|
2334
|
+
{}
|
|
2335
|
+
);
|
|
2336
|
+
}
|
|
2337
|
+
// ============================================================================
|
|
2338
|
+
// AUTHENTICATED ENDPOINTS (site user JWT required)
|
|
2339
|
+
// ============================================================================
|
|
2340
|
+
/**
|
|
2341
|
+
* Get current user profile
|
|
2342
|
+
* @param siteName - The site name
|
|
2343
|
+
*/
|
|
2344
|
+
async getMe(siteName) {
|
|
2345
|
+
return this.getSingle(
|
|
2346
|
+
this.siteUserEndpoint(siteName, "/users/me")
|
|
2347
|
+
);
|
|
2348
|
+
}
|
|
2349
|
+
/**
|
|
2350
|
+
* Update current user profile
|
|
2351
|
+
* @param siteName - The site name
|
|
2352
|
+
* @param data - Fields to update
|
|
2353
|
+
* @param csrfToken - CSRF token (required)
|
|
2354
|
+
*/
|
|
2355
|
+
async updateMe(siteName, data, csrfToken) {
|
|
2356
|
+
return this.patch(
|
|
2357
|
+
this.siteUserEndpoint(siteName, "/users/me"),
|
|
2358
|
+
data,
|
|
2359
|
+
csrfToken
|
|
2360
|
+
);
|
|
2361
|
+
}
|
|
2362
|
+
/**
|
|
2363
|
+
* Get all profile key-values
|
|
2364
|
+
* @param siteName - The site name
|
|
2365
|
+
*/
|
|
2366
|
+
async getProfile(siteName) {
|
|
2367
|
+
return this.getSingle(
|
|
2368
|
+
this.siteUserEndpoint(siteName, "/users/me/profile")
|
|
2369
|
+
);
|
|
2370
|
+
}
|
|
2371
|
+
/**
|
|
2372
|
+
* Set a profile key-value
|
|
2373
|
+
* @param siteName - The site name
|
|
2374
|
+
* @param key - Profile key (e.g., 'phone', 'whatsapp', 'address_shipping')
|
|
2375
|
+
* @param value - Profile value (string or JSON string)
|
|
2376
|
+
* @param csrfToken - CSRF token (required)
|
|
2377
|
+
*/
|
|
2378
|
+
async setProfileValue(siteName, key, value, csrfToken) {
|
|
2379
|
+
return this.update(
|
|
2380
|
+
this.siteUserEndpoint(siteName, `/users/me/profile/${encodeURIComponent(key)}`),
|
|
2381
|
+
{ value },
|
|
2382
|
+
csrfToken
|
|
2383
|
+
);
|
|
2384
|
+
}
|
|
2385
|
+
/**
|
|
2386
|
+
* Delete a profile key-value
|
|
2387
|
+
* @param siteName - The site name
|
|
2388
|
+
* @param key - Profile key to delete
|
|
2389
|
+
* @param csrfToken - CSRF token (required)
|
|
2390
|
+
*/
|
|
2391
|
+
async deleteProfileValue(siteName, key, csrfToken) {
|
|
2392
|
+
return this.delete(
|
|
2393
|
+
this.siteUserEndpoint(siteName, `/users/me/profile/${encodeURIComponent(key)}`),
|
|
2394
|
+
csrfToken
|
|
2395
|
+
);
|
|
2396
|
+
}
|
|
2397
|
+
/**
|
|
2398
|
+
* Get transaction/order history
|
|
2399
|
+
* @param siteName - The site name
|
|
2400
|
+
* @param params - Pagination params
|
|
2401
|
+
*/
|
|
2402
|
+
async getOrders(siteName, params) {
|
|
2403
|
+
return this.http.get(
|
|
2404
|
+
this.buildPath(this.siteUserEndpoint(siteName, "/users/me/orders")),
|
|
2405
|
+
params
|
|
2406
|
+
);
|
|
2407
|
+
}
|
|
2408
|
+
/**
|
|
2409
|
+
* Get single order detail
|
|
2410
|
+
* @param siteName - The site name
|
|
2411
|
+
* @param orderId - Order ID or session ID
|
|
2412
|
+
*/
|
|
2413
|
+
async getOrder(siteName, orderId) {
|
|
2414
|
+
return this.getSingle(
|
|
2415
|
+
this.siteUserEndpoint(siteName, `/users/me/orders/${encodeURIComponent(orderId)}`)
|
|
2416
|
+
);
|
|
2417
|
+
}
|
|
2418
|
+
/**
|
|
2419
|
+
* Get payment subscriptions
|
|
2420
|
+
* @param siteName - The site name
|
|
2421
|
+
* @param params - Pagination params
|
|
2422
|
+
*/
|
|
2423
|
+
async getSubscriptions(siteName, params) {
|
|
2424
|
+
return this.http.get(
|
|
2425
|
+
this.buildPath(this.siteUserEndpoint(siteName, "/users/me/subscriptions")),
|
|
2426
|
+
params
|
|
2427
|
+
);
|
|
2428
|
+
}
|
|
2429
|
+
/**
|
|
2430
|
+
* Get single subscription detail
|
|
2431
|
+
* @param siteName - The site name
|
|
2432
|
+
* @param id - Subscription ID
|
|
2433
|
+
*/
|
|
2434
|
+
async getSubscription(siteName, id) {
|
|
2435
|
+
return this.getSingle(
|
|
2436
|
+
this.siteUserEndpoint(siteName, `/users/me/subscriptions/${encodeURIComponent(id)}`)
|
|
2437
|
+
);
|
|
2438
|
+
}
|
|
2439
|
+
/**
|
|
2440
|
+
* Cancel a subscription (marks for cancellation at period end)
|
|
2441
|
+
* @param siteName - The site name
|
|
2442
|
+
* @param id - Subscription ID
|
|
2443
|
+
* @param csrfToken - CSRF token (required)
|
|
2444
|
+
*/
|
|
2445
|
+
async cancelSubscription(siteName, id, csrfToken) {
|
|
2446
|
+
return this.create(
|
|
2447
|
+
this.siteUserEndpoint(siteName, `/users/me/subscriptions/${encodeURIComponent(id)}/cancel`),
|
|
2448
|
+
{},
|
|
2449
|
+
csrfToken
|
|
2450
|
+
);
|
|
2451
|
+
}
|
|
2452
|
+
/**
|
|
2453
|
+
* Get linked newsletter subscriptions
|
|
2454
|
+
* @param siteName - The site name
|
|
2455
|
+
*/
|
|
2456
|
+
async getNewsletterSubscriptions(siteName) {
|
|
2457
|
+
return this.getSingle(
|
|
2458
|
+
this.siteUserEndpoint(siteName, "/users/me/newsletters")
|
|
2459
|
+
);
|
|
2460
|
+
}
|
|
2461
|
+
// ============================================================================
|
|
2462
|
+
// ADMIN ENDPOINTS (API key auth required)
|
|
2463
|
+
// ============================================================================
|
|
2464
|
+
/**
|
|
2465
|
+
* List all site users (admin only)
|
|
2466
|
+
* @param siteName - The site name
|
|
2467
|
+
* @param params - Query params (limit, offset, status)
|
|
2468
|
+
*/
|
|
2469
|
+
async listUsers(siteName, params) {
|
|
2470
|
+
return this.http.get(
|
|
2471
|
+
this.buildPath(this.siteUserEndpoint(siteName, "/users")),
|
|
2472
|
+
params
|
|
2473
|
+
);
|
|
2474
|
+
}
|
|
2475
|
+
/**
|
|
2476
|
+
* Get user detail (admin only)
|
|
2477
|
+
* @param siteName - The site name
|
|
2478
|
+
* @param userId - User ID
|
|
2479
|
+
*/
|
|
2480
|
+
async getUser(siteName, userId) {
|
|
2481
|
+
return this.getSingle(
|
|
2482
|
+
this.siteUserEndpoint(siteName, `/users/${encodeURIComponent(userId)}`)
|
|
2483
|
+
);
|
|
2484
|
+
}
|
|
2485
|
+
/**
|
|
2486
|
+
* Update user status (admin only)
|
|
2487
|
+
* @param siteName - The site name
|
|
2488
|
+
* @param userId - User ID
|
|
2489
|
+
* @param status - New status
|
|
2490
|
+
* @param csrfToken - CSRF token (required)
|
|
2491
|
+
*/
|
|
2492
|
+
async updateUserStatus(siteName, userId, status, csrfToken) {
|
|
2493
|
+
return this.patch(
|
|
2494
|
+
this.siteUserEndpoint(siteName, `/users/${encodeURIComponent(userId)}/status`),
|
|
2495
|
+
{ status },
|
|
2496
|
+
csrfToken
|
|
2497
|
+
);
|
|
2498
|
+
}
|
|
2499
|
+
};
|
|
2500
|
+
|
|
2178
2501
|
// src/perspect-api-client.ts
|
|
2179
2502
|
var PerspectApiClient = class {
|
|
2180
2503
|
http;
|
|
@@ -2191,6 +2514,7 @@ var PerspectApiClient = class {
|
|
|
2191
2514
|
checkout;
|
|
2192
2515
|
contact;
|
|
2193
2516
|
newsletter;
|
|
2517
|
+
siteUsers;
|
|
2194
2518
|
constructor(config) {
|
|
2195
2519
|
if (!config.baseUrl) {
|
|
2196
2520
|
throw new Error("baseUrl is required in PerspectApiConfig");
|
|
@@ -2208,6 +2532,7 @@ var PerspectApiClient = class {
|
|
|
2208
2532
|
this.checkout = new CheckoutClient(this.http, this.cache);
|
|
2209
2533
|
this.contact = new ContactClient(this.http, this.cache);
|
|
2210
2534
|
this.newsletter = new NewsletterClient(this.http, this.cache);
|
|
2535
|
+
this.siteUsers = new SiteUsersClient(this.http, this.cache);
|
|
2211
2536
|
}
|
|
2212
2537
|
/**
|
|
2213
2538
|
* Update authentication token
|
|
@@ -2896,6 +3221,7 @@ export {
|
|
|
2896
3221
|
OrganizationsClient,
|
|
2897
3222
|
PerspectApiClient,
|
|
2898
3223
|
ProductsClient,
|
|
3224
|
+
SiteUsersClient,
|
|
2899
3225
|
SitesClient,
|
|
2900
3226
|
WebhooksClient,
|
|
2901
3227
|
buildImageUrl,
|
package/package.json
CHANGED
|
@@ -371,4 +371,127 @@ export class ProductsClient extends BaseClient {
|
|
|
371
371
|
}
|
|
372
372
|
return undefined;
|
|
373
373
|
}
|
|
374
|
+
|
|
375
|
+
// ============================================================================
|
|
376
|
+
// PRODUCT OPTIONS AND SKUS (for variants)
|
|
377
|
+
// ============================================================================
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Get all options (and their values) for a product
|
|
381
|
+
*/
|
|
382
|
+
async getProductOptions(
|
|
383
|
+
siteName: string,
|
|
384
|
+
productId: number
|
|
385
|
+
): Promise<ApiResponse<Array<{
|
|
386
|
+
option_id: number;
|
|
387
|
+
option_name: string;
|
|
388
|
+
display_order: number;
|
|
389
|
+
values: Array<{
|
|
390
|
+
value_id: number;
|
|
391
|
+
value: string;
|
|
392
|
+
display_order: number;
|
|
393
|
+
}>;
|
|
394
|
+
}>>> {
|
|
395
|
+
const endpoint = this.siteScopedEndpoint(
|
|
396
|
+
siteName,
|
|
397
|
+
`/products/${productId}/options`,
|
|
398
|
+
{ includeSitesSegment: false }
|
|
399
|
+
);
|
|
400
|
+
return this.getSingle(endpoint);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Create a new product option (e.g., "Size", "Color")
|
|
405
|
+
*/
|
|
406
|
+
async createProductOption(
|
|
407
|
+
siteName: string,
|
|
408
|
+
productId: number,
|
|
409
|
+
data: { option_name: string; display_order?: number }
|
|
410
|
+
): Promise<ApiResponse<{
|
|
411
|
+
option_id: number;
|
|
412
|
+
option_name: string;
|
|
413
|
+
display_order: number;
|
|
414
|
+
}>> {
|
|
415
|
+
const endpoint = this.siteScopedEndpoint(
|
|
416
|
+
siteName,
|
|
417
|
+
`/products/${productId}/options`,
|
|
418
|
+
{ includeSitesSegment: false }
|
|
419
|
+
);
|
|
420
|
+
return this.create(endpoint, data);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Create a new value for a product option (e.g., "Small", "Red")
|
|
425
|
+
*/
|
|
426
|
+
async createProductOptionValue(
|
|
427
|
+
siteName: string,
|
|
428
|
+
productId: number,
|
|
429
|
+
optionId: number,
|
|
430
|
+
data: { value: string; display_order?: number }
|
|
431
|
+
): Promise<ApiResponse<{
|
|
432
|
+
value_id: number;
|
|
433
|
+
value: string;
|
|
434
|
+
display_order: number;
|
|
435
|
+
}>> {
|
|
436
|
+
const endpoint = this.siteScopedEndpoint(
|
|
437
|
+
siteName,
|
|
438
|
+
`/products/${productId}/options/${optionId}/values`,
|
|
439
|
+
{ includeSitesSegment: false }
|
|
440
|
+
);
|
|
441
|
+
return this.create(endpoint, data);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* Get all SKUs for a product (with their option value combinations)
|
|
446
|
+
*/
|
|
447
|
+
async getProductSkus(
|
|
448
|
+
siteName: string,
|
|
449
|
+
productId: number
|
|
450
|
+
): Promise<ApiResponse<Array<{
|
|
451
|
+
sku_id: number;
|
|
452
|
+
sku: string;
|
|
453
|
+
price?: number;
|
|
454
|
+
sale_price?: number;
|
|
455
|
+
stock_quantity?: number;
|
|
456
|
+
combination_key: string;
|
|
457
|
+
value_ids: number[];
|
|
458
|
+
created_at: string;
|
|
459
|
+
updated_at: string;
|
|
460
|
+
}>>> {
|
|
461
|
+
const endpoint = this.siteScopedEndpoint(
|
|
462
|
+
siteName,
|
|
463
|
+
`/products/${productId}/skus`,
|
|
464
|
+
{ includeSitesSegment: false }
|
|
465
|
+
);
|
|
466
|
+
return this.getSingle(endpoint);
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* Create or update a SKU for a product variant combination
|
|
471
|
+
*/
|
|
472
|
+
async createProductSku(
|
|
473
|
+
siteName: string,
|
|
474
|
+
productId: number,
|
|
475
|
+
data: {
|
|
476
|
+
sku: string;
|
|
477
|
+
price?: number | null;
|
|
478
|
+
sale_price?: number | null;
|
|
479
|
+
stock_quantity?: number | null;
|
|
480
|
+
value_ids: number[];
|
|
481
|
+
}
|
|
482
|
+
): Promise<ApiResponse<{
|
|
483
|
+
sku_id: number;
|
|
484
|
+
sku: string;
|
|
485
|
+
price?: number;
|
|
486
|
+
sale_price?: number;
|
|
487
|
+
stock_quantity?: number;
|
|
488
|
+
combination_key: string;
|
|
489
|
+
}>> {
|
|
490
|
+
const endpoint = this.siteScopedEndpoint(
|
|
491
|
+
siteName,
|
|
492
|
+
`/products/${productId}/skus`,
|
|
493
|
+
{ includeSitesSegment: false }
|
|
494
|
+
);
|
|
495
|
+
return this.create(endpoint, data);
|
|
496
|
+
}
|
|
374
497
|
}
|