brainerce 1.23.14 → 1.25.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 +1 -0
- package/dist/index.d.mts +119 -0
- package/dist/index.d.ts +119 -0
- package/dist/index.js +166 -0
- package/dist/index.mjs +166 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -48,6 +48,7 @@ Every Brainerce storefront must include **all mandatory features** below. Featur
|
|
|
48
48
|
| Account area (profile + order history) | `client.getMyProfile()`, `client.getMyOrders()` | ✅ |
|
|
49
49
|
| Global header: cart count + search autocomplete | `client.getCart()`, `client.getSearchSuggestions(query)` | ✅ |
|
|
50
50
|
| Discount banners + product badges | `client.getDiscountBanners()`, `client.getProductDiscountBadge(productId)` | ✅ |
|
|
51
|
+
| Product reviews on PDP + JSON-LD aggregateRating | `client.listProductReviews(id)`, `client.submitProductReview(id, …)` | ✅ |
|
|
51
52
|
| Multi-language + RTL (when i18n enabled) | `client.setLocale()` | conditional |
|
|
52
53
|
|
|
53
54
|
---
|
package/dist/index.d.mts
CHANGED
|
@@ -323,9 +323,55 @@ interface Product {
|
|
|
323
323
|
* (`getProductBySlug`, `getProductById`); omitted from list responses.
|
|
324
324
|
*/
|
|
325
325
|
modifierGroups?: ModifierGroup[];
|
|
326
|
+
/** Average rating across visible reviews (0 when reviewCount is 0). */
|
|
327
|
+
avgRating?: number;
|
|
328
|
+
/** Count of visible reviews (non-hidden). */
|
|
329
|
+
reviewCount?: number;
|
|
326
330
|
createdAt: string;
|
|
327
331
|
updatedAt: string;
|
|
328
332
|
}
|
|
333
|
+
/**
|
|
334
|
+
* Product review submitted by a customer.
|
|
335
|
+
* Reviews publish immediately (no PENDING state). Merchants hide via the admin
|
|
336
|
+
* surface — hiddenAt is null for visible reviews.
|
|
337
|
+
*/
|
|
338
|
+
interface ProductReview {
|
|
339
|
+
id: string;
|
|
340
|
+
productId: string;
|
|
341
|
+
authorName: string;
|
|
342
|
+
rating: number;
|
|
343
|
+
body: string | null;
|
|
344
|
+
verifiedPurchase: boolean;
|
|
345
|
+
/** Only present in admin responses; null on storefront responses. */
|
|
346
|
+
hiddenAt?: string | null;
|
|
347
|
+
createdAt: string;
|
|
348
|
+
}
|
|
349
|
+
/** Admin-mode review with full PII. Returned by `client.adminReviews.*`. */
|
|
350
|
+
interface ProductReviewAdmin extends ProductReview {
|
|
351
|
+
customerId: string | null;
|
|
352
|
+
authorEmail: string | null;
|
|
353
|
+
orderId: string | null;
|
|
354
|
+
updatedAt: string;
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Body for customer-authenticated submit / update.
|
|
358
|
+
* Author name + email are derived server-side from the customer profile.
|
|
359
|
+
*/
|
|
360
|
+
interface WriteProductReviewInput {
|
|
361
|
+
rating: number;
|
|
362
|
+
body?: string;
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Returned by `client.getMyProductReview(productId)`. Tells the storefront which
|
|
366
|
+
* UI to render: sign-in / not-eligible / submit / edit.
|
|
367
|
+
*/
|
|
368
|
+
interface MyProductReview {
|
|
369
|
+
eligible: boolean;
|
|
370
|
+
/** Machine-readable reason when not eligible. null when eligible=true. */
|
|
371
|
+
reason: 'no_eligible_order' | 'reviews_disabled' | 'product_not_found' | null;
|
|
372
|
+
/** The customer's existing review for this product, or null. */
|
|
373
|
+
myReview: ProductReview | null;
|
|
374
|
+
}
|
|
329
375
|
interface ProductImage {
|
|
330
376
|
url: string;
|
|
331
377
|
position?: number;
|
|
@@ -6081,6 +6127,79 @@ declare class BrainerceClient {
|
|
|
6081
6127
|
* ```
|
|
6082
6128
|
*/
|
|
6083
6129
|
getProductRecommendations(productId: string, type?: ProductRelationType): Promise<ProductRecommendationsResponse>;
|
|
6130
|
+
/**
|
|
6131
|
+
* List visible reviews for a product (storefront / sales-channel modes).
|
|
6132
|
+
* Reviews that the merchant has hidden are excluded.
|
|
6133
|
+
*
|
|
6134
|
+
* @example
|
|
6135
|
+
* ```typescript
|
|
6136
|
+
* const { data, meta } = await client.listProductReviews('prod_123', { page: 1, limit: 20 });
|
|
6137
|
+
* data.forEach(r => console.log(r.rating, r.body, r.verifiedPurchase));
|
|
6138
|
+
* ```
|
|
6139
|
+
*/
|
|
6140
|
+
listProductReviews(productId: string, params?: {
|
|
6141
|
+
page?: number;
|
|
6142
|
+
limit?: number;
|
|
6143
|
+
}): Promise<PaginatedResponse<ProductReview>>;
|
|
6144
|
+
/**
|
|
6145
|
+
* Get the current customer's review state for a product (storefront / sales-channel modes).
|
|
6146
|
+
* Requires a customer token (`setCustomerToken(...)` after login).
|
|
6147
|
+
*
|
|
6148
|
+
* Returns whether the customer is *eligible* to review (only purchasers are),
|
|
6149
|
+
* and their existing review for this product if any.
|
|
6150
|
+
*
|
|
6151
|
+
* @example
|
|
6152
|
+
* ```typescript
|
|
6153
|
+
* const { eligible, reason, myReview } = await client.getMyProductReview('prod_123');
|
|
6154
|
+
* if (!eligible) showMessage(reason); // 'no_eligible_order' | 'reviews_disabled' | …
|
|
6155
|
+
* else if (myReview) renderEditForm(myReview);
|
|
6156
|
+
* else renderSubmitForm();
|
|
6157
|
+
* ```
|
|
6158
|
+
*/
|
|
6159
|
+
getMyProductReview(productId: string): Promise<MyProductReview>;
|
|
6160
|
+
/**
|
|
6161
|
+
* Submit a customer review for a product (storefront / sales-channel modes).
|
|
6162
|
+
* Requires customer authentication AND that the customer has purchased the
|
|
6163
|
+
* product (SHIPPED for physical, PAID for downloadable).
|
|
6164
|
+
*
|
|
6165
|
+
* 403 `no_eligible_order` if the customer didn't purchase the product.
|
|
6166
|
+
* 409 `Conflict` if they already submitted a review (use `updateMyProductReview` instead).
|
|
6167
|
+
*
|
|
6168
|
+
* Author name + email are derived server-side from the customer profile.
|
|
6169
|
+
*
|
|
6170
|
+
* @example
|
|
6171
|
+
* ```typescript
|
|
6172
|
+
* const review = await client.submitProductReview('prod_123', {
|
|
6173
|
+
* rating: 5,
|
|
6174
|
+
* body: 'Loved it!',
|
|
6175
|
+
* });
|
|
6176
|
+
* ```
|
|
6177
|
+
*/
|
|
6178
|
+
submitProductReview(productId: string, input: WriteProductReviewInput): Promise<ProductReview>;
|
|
6179
|
+
/**
|
|
6180
|
+
* Edit your own review on a product (storefront / sales-channel modes).
|
|
6181
|
+
* Only updates rating + body; the author name/email and verifiedPurchase flag
|
|
6182
|
+
* are preserved from the original submit.
|
|
6183
|
+
*/
|
|
6184
|
+
updateMyProductReview(productId: string, input: WriteProductReviewInput): Promise<ProductReview>;
|
|
6185
|
+
/**
|
|
6186
|
+
* Delete your own review on a product (storefront / sales-channel modes).
|
|
6187
|
+
* After deletion the customer is free to submit a new review (subject to eligibility).
|
|
6188
|
+
*/
|
|
6189
|
+
deleteMyProductReview(productId: string): Promise<void>;
|
|
6190
|
+
/**
|
|
6191
|
+
* Admin: list all reviews for a product (incl. hidden). Requires API key with `reviews:read`.
|
|
6192
|
+
*/
|
|
6193
|
+
adminListProductReviews(productId: string, params?: {
|
|
6194
|
+
storeId?: string;
|
|
6195
|
+
page?: number;
|
|
6196
|
+
limit?: number;
|
|
6197
|
+
visibility?: 'visible' | 'hidden' | 'all';
|
|
6198
|
+
}): Promise<PaginatedResponse<ProductReviewAdmin>>;
|
|
6199
|
+
/** Admin: hide a review (sets hiddenAt). */
|
|
6200
|
+
hideProductReview(reviewId: string, storeId?: string): Promise<ProductReviewAdmin>;
|
|
6201
|
+
/** Admin: unhide a previously hidden review. */
|
|
6202
|
+
showProductReview(reviewId: string, storeId?: string): Promise<ProductReviewAdmin>;
|
|
6084
6203
|
/**
|
|
6085
6204
|
* Get cross-sell recommendations based on cart contents.
|
|
6086
6205
|
* Returns products that complement items already in the cart.
|
package/dist/index.d.ts
CHANGED
|
@@ -323,9 +323,55 @@ interface Product {
|
|
|
323
323
|
* (`getProductBySlug`, `getProductById`); omitted from list responses.
|
|
324
324
|
*/
|
|
325
325
|
modifierGroups?: ModifierGroup[];
|
|
326
|
+
/** Average rating across visible reviews (0 when reviewCount is 0). */
|
|
327
|
+
avgRating?: number;
|
|
328
|
+
/** Count of visible reviews (non-hidden). */
|
|
329
|
+
reviewCount?: number;
|
|
326
330
|
createdAt: string;
|
|
327
331
|
updatedAt: string;
|
|
328
332
|
}
|
|
333
|
+
/**
|
|
334
|
+
* Product review submitted by a customer.
|
|
335
|
+
* Reviews publish immediately (no PENDING state). Merchants hide via the admin
|
|
336
|
+
* surface — hiddenAt is null for visible reviews.
|
|
337
|
+
*/
|
|
338
|
+
interface ProductReview {
|
|
339
|
+
id: string;
|
|
340
|
+
productId: string;
|
|
341
|
+
authorName: string;
|
|
342
|
+
rating: number;
|
|
343
|
+
body: string | null;
|
|
344
|
+
verifiedPurchase: boolean;
|
|
345
|
+
/** Only present in admin responses; null on storefront responses. */
|
|
346
|
+
hiddenAt?: string | null;
|
|
347
|
+
createdAt: string;
|
|
348
|
+
}
|
|
349
|
+
/** Admin-mode review with full PII. Returned by `client.adminReviews.*`. */
|
|
350
|
+
interface ProductReviewAdmin extends ProductReview {
|
|
351
|
+
customerId: string | null;
|
|
352
|
+
authorEmail: string | null;
|
|
353
|
+
orderId: string | null;
|
|
354
|
+
updatedAt: string;
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Body for customer-authenticated submit / update.
|
|
358
|
+
* Author name + email are derived server-side from the customer profile.
|
|
359
|
+
*/
|
|
360
|
+
interface WriteProductReviewInput {
|
|
361
|
+
rating: number;
|
|
362
|
+
body?: string;
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Returned by `client.getMyProductReview(productId)`. Tells the storefront which
|
|
366
|
+
* UI to render: sign-in / not-eligible / submit / edit.
|
|
367
|
+
*/
|
|
368
|
+
interface MyProductReview {
|
|
369
|
+
eligible: boolean;
|
|
370
|
+
/** Machine-readable reason when not eligible. null when eligible=true. */
|
|
371
|
+
reason: 'no_eligible_order' | 'reviews_disabled' | 'product_not_found' | null;
|
|
372
|
+
/** The customer's existing review for this product, or null. */
|
|
373
|
+
myReview: ProductReview | null;
|
|
374
|
+
}
|
|
329
375
|
interface ProductImage {
|
|
330
376
|
url: string;
|
|
331
377
|
position?: number;
|
|
@@ -6081,6 +6127,79 @@ declare class BrainerceClient {
|
|
|
6081
6127
|
* ```
|
|
6082
6128
|
*/
|
|
6083
6129
|
getProductRecommendations(productId: string, type?: ProductRelationType): Promise<ProductRecommendationsResponse>;
|
|
6130
|
+
/**
|
|
6131
|
+
* List visible reviews for a product (storefront / sales-channel modes).
|
|
6132
|
+
* Reviews that the merchant has hidden are excluded.
|
|
6133
|
+
*
|
|
6134
|
+
* @example
|
|
6135
|
+
* ```typescript
|
|
6136
|
+
* const { data, meta } = await client.listProductReviews('prod_123', { page: 1, limit: 20 });
|
|
6137
|
+
* data.forEach(r => console.log(r.rating, r.body, r.verifiedPurchase));
|
|
6138
|
+
* ```
|
|
6139
|
+
*/
|
|
6140
|
+
listProductReviews(productId: string, params?: {
|
|
6141
|
+
page?: number;
|
|
6142
|
+
limit?: number;
|
|
6143
|
+
}): Promise<PaginatedResponse<ProductReview>>;
|
|
6144
|
+
/**
|
|
6145
|
+
* Get the current customer's review state for a product (storefront / sales-channel modes).
|
|
6146
|
+
* Requires a customer token (`setCustomerToken(...)` after login).
|
|
6147
|
+
*
|
|
6148
|
+
* Returns whether the customer is *eligible* to review (only purchasers are),
|
|
6149
|
+
* and their existing review for this product if any.
|
|
6150
|
+
*
|
|
6151
|
+
* @example
|
|
6152
|
+
* ```typescript
|
|
6153
|
+
* const { eligible, reason, myReview } = await client.getMyProductReview('prod_123');
|
|
6154
|
+
* if (!eligible) showMessage(reason); // 'no_eligible_order' | 'reviews_disabled' | …
|
|
6155
|
+
* else if (myReview) renderEditForm(myReview);
|
|
6156
|
+
* else renderSubmitForm();
|
|
6157
|
+
* ```
|
|
6158
|
+
*/
|
|
6159
|
+
getMyProductReview(productId: string): Promise<MyProductReview>;
|
|
6160
|
+
/**
|
|
6161
|
+
* Submit a customer review for a product (storefront / sales-channel modes).
|
|
6162
|
+
* Requires customer authentication AND that the customer has purchased the
|
|
6163
|
+
* product (SHIPPED for physical, PAID for downloadable).
|
|
6164
|
+
*
|
|
6165
|
+
* 403 `no_eligible_order` if the customer didn't purchase the product.
|
|
6166
|
+
* 409 `Conflict` if they already submitted a review (use `updateMyProductReview` instead).
|
|
6167
|
+
*
|
|
6168
|
+
* Author name + email are derived server-side from the customer profile.
|
|
6169
|
+
*
|
|
6170
|
+
* @example
|
|
6171
|
+
* ```typescript
|
|
6172
|
+
* const review = await client.submitProductReview('prod_123', {
|
|
6173
|
+
* rating: 5,
|
|
6174
|
+
* body: 'Loved it!',
|
|
6175
|
+
* });
|
|
6176
|
+
* ```
|
|
6177
|
+
*/
|
|
6178
|
+
submitProductReview(productId: string, input: WriteProductReviewInput): Promise<ProductReview>;
|
|
6179
|
+
/**
|
|
6180
|
+
* Edit your own review on a product (storefront / sales-channel modes).
|
|
6181
|
+
* Only updates rating + body; the author name/email and verifiedPurchase flag
|
|
6182
|
+
* are preserved from the original submit.
|
|
6183
|
+
*/
|
|
6184
|
+
updateMyProductReview(productId: string, input: WriteProductReviewInput): Promise<ProductReview>;
|
|
6185
|
+
/**
|
|
6186
|
+
* Delete your own review on a product (storefront / sales-channel modes).
|
|
6187
|
+
* After deletion the customer is free to submit a new review (subject to eligibility).
|
|
6188
|
+
*/
|
|
6189
|
+
deleteMyProductReview(productId: string): Promise<void>;
|
|
6190
|
+
/**
|
|
6191
|
+
* Admin: list all reviews for a product (incl. hidden). Requires API key with `reviews:read`.
|
|
6192
|
+
*/
|
|
6193
|
+
adminListProductReviews(productId: string, params?: {
|
|
6194
|
+
storeId?: string;
|
|
6195
|
+
page?: number;
|
|
6196
|
+
limit?: number;
|
|
6197
|
+
visibility?: 'visible' | 'hidden' | 'all';
|
|
6198
|
+
}): Promise<PaginatedResponse<ProductReviewAdmin>>;
|
|
6199
|
+
/** Admin: hide a review (sets hiddenAt). */
|
|
6200
|
+
hideProductReview(reviewId: string, storeId?: string): Promise<ProductReviewAdmin>;
|
|
6201
|
+
/** Admin: unhide a previously hidden review. */
|
|
6202
|
+
showProductReview(reviewId: string, storeId?: string): Promise<ProductReviewAdmin>;
|
|
6084
6203
|
/**
|
|
6085
6204
|
* Get cross-sell recommendations based on cart contents.
|
|
6086
6205
|
* Returns products that complement items already in the cart.
|
package/dist/index.js
CHANGED
|
@@ -2790,6 +2790,172 @@ var BrainerceClient = class {
|
|
|
2790
2790
|
400
|
|
2791
2791
|
);
|
|
2792
2792
|
}
|
|
2793
|
+
// ===================================================
|
|
2794
|
+
// Product Reviews
|
|
2795
|
+
// ===================================================
|
|
2796
|
+
/**
|
|
2797
|
+
* List visible reviews for a product (storefront / sales-channel modes).
|
|
2798
|
+
* Reviews that the merchant has hidden are excluded.
|
|
2799
|
+
*
|
|
2800
|
+
* @example
|
|
2801
|
+
* ```typescript
|
|
2802
|
+
* const { data, meta } = await client.listProductReviews('prod_123', { page: 1, limit: 20 });
|
|
2803
|
+
* data.forEach(r => console.log(r.rating, r.body, r.verifiedPurchase));
|
|
2804
|
+
* ```
|
|
2805
|
+
*/
|
|
2806
|
+
async listProductReviews(productId, params) {
|
|
2807
|
+
const queryParams = {};
|
|
2808
|
+
if (params?.page) queryParams.page = params.page;
|
|
2809
|
+
if (params?.limit) queryParams.limit = params.limit;
|
|
2810
|
+
if (this.isVibeCodedMode()) {
|
|
2811
|
+
return this.vibeCodedRequest(
|
|
2812
|
+
"GET",
|
|
2813
|
+
`/products/${productId}/reviews`,
|
|
2814
|
+
void 0,
|
|
2815
|
+
queryParams
|
|
2816
|
+
);
|
|
2817
|
+
}
|
|
2818
|
+
if (this.storeId && !this.apiKey) {
|
|
2819
|
+
return this.storefrontRequest(
|
|
2820
|
+
"GET",
|
|
2821
|
+
`/products/${productId}/reviews`,
|
|
2822
|
+
void 0,
|
|
2823
|
+
queryParams
|
|
2824
|
+
);
|
|
2825
|
+
}
|
|
2826
|
+
throw new BrainerceError("listProductReviews() requires vibe-coded or storefront mode", 400);
|
|
2827
|
+
}
|
|
2828
|
+
/**
|
|
2829
|
+
* Get the current customer's review state for a product (storefront / sales-channel modes).
|
|
2830
|
+
* Requires a customer token (`setCustomerToken(...)` after login).
|
|
2831
|
+
*
|
|
2832
|
+
* Returns whether the customer is *eligible* to review (only purchasers are),
|
|
2833
|
+
* and their existing review for this product if any.
|
|
2834
|
+
*
|
|
2835
|
+
* @example
|
|
2836
|
+
* ```typescript
|
|
2837
|
+
* const { eligible, reason, myReview } = await client.getMyProductReview('prod_123');
|
|
2838
|
+
* if (!eligible) showMessage(reason); // 'no_eligible_order' | 'reviews_disabled' | …
|
|
2839
|
+
* else if (myReview) renderEditForm(myReview);
|
|
2840
|
+
* else renderSubmitForm();
|
|
2841
|
+
* ```
|
|
2842
|
+
*/
|
|
2843
|
+
async getMyProductReview(productId) {
|
|
2844
|
+
if (this.isVibeCodedMode()) {
|
|
2845
|
+
return this.vibeCodedRequest("GET", `/products/${productId}/reviews/me`);
|
|
2846
|
+
}
|
|
2847
|
+
if (this.storeId && !this.apiKey) {
|
|
2848
|
+
return this.storefrontRequest("GET", `/products/${productId}/reviews/me`);
|
|
2849
|
+
}
|
|
2850
|
+
throw new BrainerceError("getMyProductReview() requires vibe-coded or storefront mode", 400);
|
|
2851
|
+
}
|
|
2852
|
+
/**
|
|
2853
|
+
* Submit a customer review for a product (storefront / sales-channel modes).
|
|
2854
|
+
* Requires customer authentication AND that the customer has purchased the
|
|
2855
|
+
* product (SHIPPED for physical, PAID for downloadable).
|
|
2856
|
+
*
|
|
2857
|
+
* 403 `no_eligible_order` if the customer didn't purchase the product.
|
|
2858
|
+
* 409 `Conflict` if they already submitted a review (use `updateMyProductReview` instead).
|
|
2859
|
+
*
|
|
2860
|
+
* Author name + email are derived server-side from the customer profile.
|
|
2861
|
+
*
|
|
2862
|
+
* @example
|
|
2863
|
+
* ```typescript
|
|
2864
|
+
* const review = await client.submitProductReview('prod_123', {
|
|
2865
|
+
* rating: 5,
|
|
2866
|
+
* body: 'Loved it!',
|
|
2867
|
+
* });
|
|
2868
|
+
* ```
|
|
2869
|
+
*/
|
|
2870
|
+
async submitProductReview(productId, input) {
|
|
2871
|
+
if (this.isVibeCodedMode()) {
|
|
2872
|
+
return this.vibeCodedRequest("POST", `/products/${productId}/reviews`, input);
|
|
2873
|
+
}
|
|
2874
|
+
if (this.storeId && !this.apiKey) {
|
|
2875
|
+
return this.storefrontRequest("POST", `/products/${productId}/reviews`, input);
|
|
2876
|
+
}
|
|
2877
|
+
throw new BrainerceError("submitProductReview() requires vibe-coded or storefront mode", 400);
|
|
2878
|
+
}
|
|
2879
|
+
/**
|
|
2880
|
+
* Edit your own review on a product (storefront / sales-channel modes).
|
|
2881
|
+
* Only updates rating + body; the author name/email and verifiedPurchase flag
|
|
2882
|
+
* are preserved from the original submit.
|
|
2883
|
+
*/
|
|
2884
|
+
async updateMyProductReview(productId, input) {
|
|
2885
|
+
if (this.isVibeCodedMode()) {
|
|
2886
|
+
return this.vibeCodedRequest(
|
|
2887
|
+
"PATCH",
|
|
2888
|
+
`/products/${productId}/reviews/me`,
|
|
2889
|
+
input
|
|
2890
|
+
);
|
|
2891
|
+
}
|
|
2892
|
+
if (this.storeId && !this.apiKey) {
|
|
2893
|
+
return this.storefrontRequest(
|
|
2894
|
+
"PATCH",
|
|
2895
|
+
`/products/${productId}/reviews/me`,
|
|
2896
|
+
input
|
|
2897
|
+
);
|
|
2898
|
+
}
|
|
2899
|
+
throw new BrainerceError("updateMyProductReview() requires vibe-coded or storefront mode", 400);
|
|
2900
|
+
}
|
|
2901
|
+
/**
|
|
2902
|
+
* Delete your own review on a product (storefront / sales-channel modes).
|
|
2903
|
+
* After deletion the customer is free to submit a new review (subject to eligibility).
|
|
2904
|
+
*/
|
|
2905
|
+
async deleteMyProductReview(productId) {
|
|
2906
|
+
if (this.isVibeCodedMode()) {
|
|
2907
|
+
await this.vibeCodedRequest("DELETE", `/products/${productId}/reviews/me`);
|
|
2908
|
+
return;
|
|
2909
|
+
}
|
|
2910
|
+
if (this.storeId && !this.apiKey) {
|
|
2911
|
+
await this.storefrontRequest("DELETE", `/products/${productId}/reviews/me`);
|
|
2912
|
+
return;
|
|
2913
|
+
}
|
|
2914
|
+
throw new BrainerceError("deleteMyProductReview() requires vibe-coded or storefront mode", 400);
|
|
2915
|
+
}
|
|
2916
|
+
/**
|
|
2917
|
+
* Admin: list all reviews for a product (incl. hidden). Requires API key with `reviews:read`.
|
|
2918
|
+
*/
|
|
2919
|
+
async adminListProductReviews(productId, params) {
|
|
2920
|
+
if (!this.apiKey) {
|
|
2921
|
+
throw new BrainerceError("adminListProductReviews() requires admin (API key) mode", 400);
|
|
2922
|
+
}
|
|
2923
|
+
const queryParams = {};
|
|
2924
|
+
if (params?.storeId) queryParams.storeId = params.storeId;
|
|
2925
|
+
if (params?.page) queryParams.page = params.page;
|
|
2926
|
+
if (params?.limit) queryParams.limit = params.limit;
|
|
2927
|
+
if (params?.visibility) queryParams.visibility = params.visibility;
|
|
2928
|
+
return this.adminRequest(
|
|
2929
|
+
"GET",
|
|
2930
|
+
`/api/v1/products/${productId}/reviews`,
|
|
2931
|
+
void 0,
|
|
2932
|
+
queryParams
|
|
2933
|
+
);
|
|
2934
|
+
}
|
|
2935
|
+
/** Admin: hide a review (sets hiddenAt). */
|
|
2936
|
+
async hideProductReview(reviewId, storeId) {
|
|
2937
|
+
if (!this.apiKey) {
|
|
2938
|
+
throw new BrainerceError("hideProductReview() requires admin (API key) mode", 400);
|
|
2939
|
+
}
|
|
2940
|
+
return this.adminRequest(
|
|
2941
|
+
"PATCH",
|
|
2942
|
+
`/api/v1/reviews/${reviewId}/hide`,
|
|
2943
|
+
void 0,
|
|
2944
|
+
storeId ? { storeId } : void 0
|
|
2945
|
+
);
|
|
2946
|
+
}
|
|
2947
|
+
/** Admin: unhide a previously hidden review. */
|
|
2948
|
+
async showProductReview(reviewId, storeId) {
|
|
2949
|
+
if (!this.apiKey) {
|
|
2950
|
+
throw new BrainerceError("showProductReview() requires admin (API key) mode", 400);
|
|
2951
|
+
}
|
|
2952
|
+
return this.adminRequest(
|
|
2953
|
+
"PATCH",
|
|
2954
|
+
`/api/v1/reviews/${reviewId}/show`,
|
|
2955
|
+
void 0,
|
|
2956
|
+
storeId ? { storeId } : void 0
|
|
2957
|
+
);
|
|
2958
|
+
}
|
|
2793
2959
|
/**
|
|
2794
2960
|
* Get cross-sell recommendations based on cart contents.
|
|
2795
2961
|
* Returns products that complement items already in the cart.
|
package/dist/index.mjs
CHANGED
|
@@ -2727,6 +2727,172 @@ var BrainerceClient = class {
|
|
|
2727
2727
|
400
|
|
2728
2728
|
);
|
|
2729
2729
|
}
|
|
2730
|
+
// ===================================================
|
|
2731
|
+
// Product Reviews
|
|
2732
|
+
// ===================================================
|
|
2733
|
+
/**
|
|
2734
|
+
* List visible reviews for a product (storefront / sales-channel modes).
|
|
2735
|
+
* Reviews that the merchant has hidden are excluded.
|
|
2736
|
+
*
|
|
2737
|
+
* @example
|
|
2738
|
+
* ```typescript
|
|
2739
|
+
* const { data, meta } = await client.listProductReviews('prod_123', { page: 1, limit: 20 });
|
|
2740
|
+
* data.forEach(r => console.log(r.rating, r.body, r.verifiedPurchase));
|
|
2741
|
+
* ```
|
|
2742
|
+
*/
|
|
2743
|
+
async listProductReviews(productId, params) {
|
|
2744
|
+
const queryParams = {};
|
|
2745
|
+
if (params?.page) queryParams.page = params.page;
|
|
2746
|
+
if (params?.limit) queryParams.limit = params.limit;
|
|
2747
|
+
if (this.isVibeCodedMode()) {
|
|
2748
|
+
return this.vibeCodedRequest(
|
|
2749
|
+
"GET",
|
|
2750
|
+
`/products/${productId}/reviews`,
|
|
2751
|
+
void 0,
|
|
2752
|
+
queryParams
|
|
2753
|
+
);
|
|
2754
|
+
}
|
|
2755
|
+
if (this.storeId && !this.apiKey) {
|
|
2756
|
+
return this.storefrontRequest(
|
|
2757
|
+
"GET",
|
|
2758
|
+
`/products/${productId}/reviews`,
|
|
2759
|
+
void 0,
|
|
2760
|
+
queryParams
|
|
2761
|
+
);
|
|
2762
|
+
}
|
|
2763
|
+
throw new BrainerceError("listProductReviews() requires vibe-coded or storefront mode", 400);
|
|
2764
|
+
}
|
|
2765
|
+
/**
|
|
2766
|
+
* Get the current customer's review state for a product (storefront / sales-channel modes).
|
|
2767
|
+
* Requires a customer token (`setCustomerToken(...)` after login).
|
|
2768
|
+
*
|
|
2769
|
+
* Returns whether the customer is *eligible* to review (only purchasers are),
|
|
2770
|
+
* and their existing review for this product if any.
|
|
2771
|
+
*
|
|
2772
|
+
* @example
|
|
2773
|
+
* ```typescript
|
|
2774
|
+
* const { eligible, reason, myReview } = await client.getMyProductReview('prod_123');
|
|
2775
|
+
* if (!eligible) showMessage(reason); // 'no_eligible_order' | 'reviews_disabled' | …
|
|
2776
|
+
* else if (myReview) renderEditForm(myReview);
|
|
2777
|
+
* else renderSubmitForm();
|
|
2778
|
+
* ```
|
|
2779
|
+
*/
|
|
2780
|
+
async getMyProductReview(productId) {
|
|
2781
|
+
if (this.isVibeCodedMode()) {
|
|
2782
|
+
return this.vibeCodedRequest("GET", `/products/${productId}/reviews/me`);
|
|
2783
|
+
}
|
|
2784
|
+
if (this.storeId && !this.apiKey) {
|
|
2785
|
+
return this.storefrontRequest("GET", `/products/${productId}/reviews/me`);
|
|
2786
|
+
}
|
|
2787
|
+
throw new BrainerceError("getMyProductReview() requires vibe-coded or storefront mode", 400);
|
|
2788
|
+
}
|
|
2789
|
+
/**
|
|
2790
|
+
* Submit a customer review for a product (storefront / sales-channel modes).
|
|
2791
|
+
* Requires customer authentication AND that the customer has purchased the
|
|
2792
|
+
* product (SHIPPED for physical, PAID for downloadable).
|
|
2793
|
+
*
|
|
2794
|
+
* 403 `no_eligible_order` if the customer didn't purchase the product.
|
|
2795
|
+
* 409 `Conflict` if they already submitted a review (use `updateMyProductReview` instead).
|
|
2796
|
+
*
|
|
2797
|
+
* Author name + email are derived server-side from the customer profile.
|
|
2798
|
+
*
|
|
2799
|
+
* @example
|
|
2800
|
+
* ```typescript
|
|
2801
|
+
* const review = await client.submitProductReview('prod_123', {
|
|
2802
|
+
* rating: 5,
|
|
2803
|
+
* body: 'Loved it!',
|
|
2804
|
+
* });
|
|
2805
|
+
* ```
|
|
2806
|
+
*/
|
|
2807
|
+
async submitProductReview(productId, input) {
|
|
2808
|
+
if (this.isVibeCodedMode()) {
|
|
2809
|
+
return this.vibeCodedRequest("POST", `/products/${productId}/reviews`, input);
|
|
2810
|
+
}
|
|
2811
|
+
if (this.storeId && !this.apiKey) {
|
|
2812
|
+
return this.storefrontRequest("POST", `/products/${productId}/reviews`, input);
|
|
2813
|
+
}
|
|
2814
|
+
throw new BrainerceError("submitProductReview() requires vibe-coded or storefront mode", 400);
|
|
2815
|
+
}
|
|
2816
|
+
/**
|
|
2817
|
+
* Edit your own review on a product (storefront / sales-channel modes).
|
|
2818
|
+
* Only updates rating + body; the author name/email and verifiedPurchase flag
|
|
2819
|
+
* are preserved from the original submit.
|
|
2820
|
+
*/
|
|
2821
|
+
async updateMyProductReview(productId, input) {
|
|
2822
|
+
if (this.isVibeCodedMode()) {
|
|
2823
|
+
return this.vibeCodedRequest(
|
|
2824
|
+
"PATCH",
|
|
2825
|
+
`/products/${productId}/reviews/me`,
|
|
2826
|
+
input
|
|
2827
|
+
);
|
|
2828
|
+
}
|
|
2829
|
+
if (this.storeId && !this.apiKey) {
|
|
2830
|
+
return this.storefrontRequest(
|
|
2831
|
+
"PATCH",
|
|
2832
|
+
`/products/${productId}/reviews/me`,
|
|
2833
|
+
input
|
|
2834
|
+
);
|
|
2835
|
+
}
|
|
2836
|
+
throw new BrainerceError("updateMyProductReview() requires vibe-coded or storefront mode", 400);
|
|
2837
|
+
}
|
|
2838
|
+
/**
|
|
2839
|
+
* Delete your own review on a product (storefront / sales-channel modes).
|
|
2840
|
+
* After deletion the customer is free to submit a new review (subject to eligibility).
|
|
2841
|
+
*/
|
|
2842
|
+
async deleteMyProductReview(productId) {
|
|
2843
|
+
if (this.isVibeCodedMode()) {
|
|
2844
|
+
await this.vibeCodedRequest("DELETE", `/products/${productId}/reviews/me`);
|
|
2845
|
+
return;
|
|
2846
|
+
}
|
|
2847
|
+
if (this.storeId && !this.apiKey) {
|
|
2848
|
+
await this.storefrontRequest("DELETE", `/products/${productId}/reviews/me`);
|
|
2849
|
+
return;
|
|
2850
|
+
}
|
|
2851
|
+
throw new BrainerceError("deleteMyProductReview() requires vibe-coded or storefront mode", 400);
|
|
2852
|
+
}
|
|
2853
|
+
/**
|
|
2854
|
+
* Admin: list all reviews for a product (incl. hidden). Requires API key with `reviews:read`.
|
|
2855
|
+
*/
|
|
2856
|
+
async adminListProductReviews(productId, params) {
|
|
2857
|
+
if (!this.apiKey) {
|
|
2858
|
+
throw new BrainerceError("adminListProductReviews() requires admin (API key) mode", 400);
|
|
2859
|
+
}
|
|
2860
|
+
const queryParams = {};
|
|
2861
|
+
if (params?.storeId) queryParams.storeId = params.storeId;
|
|
2862
|
+
if (params?.page) queryParams.page = params.page;
|
|
2863
|
+
if (params?.limit) queryParams.limit = params.limit;
|
|
2864
|
+
if (params?.visibility) queryParams.visibility = params.visibility;
|
|
2865
|
+
return this.adminRequest(
|
|
2866
|
+
"GET",
|
|
2867
|
+
`/api/v1/products/${productId}/reviews`,
|
|
2868
|
+
void 0,
|
|
2869
|
+
queryParams
|
|
2870
|
+
);
|
|
2871
|
+
}
|
|
2872
|
+
/** Admin: hide a review (sets hiddenAt). */
|
|
2873
|
+
async hideProductReview(reviewId, storeId) {
|
|
2874
|
+
if (!this.apiKey) {
|
|
2875
|
+
throw new BrainerceError("hideProductReview() requires admin (API key) mode", 400);
|
|
2876
|
+
}
|
|
2877
|
+
return this.adminRequest(
|
|
2878
|
+
"PATCH",
|
|
2879
|
+
`/api/v1/reviews/${reviewId}/hide`,
|
|
2880
|
+
void 0,
|
|
2881
|
+
storeId ? { storeId } : void 0
|
|
2882
|
+
);
|
|
2883
|
+
}
|
|
2884
|
+
/** Admin: unhide a previously hidden review. */
|
|
2885
|
+
async showProductReview(reviewId, storeId) {
|
|
2886
|
+
if (!this.apiKey) {
|
|
2887
|
+
throw new BrainerceError("showProductReview() requires admin (API key) mode", 400);
|
|
2888
|
+
}
|
|
2889
|
+
return this.adminRequest(
|
|
2890
|
+
"PATCH",
|
|
2891
|
+
`/api/v1/reviews/${reviewId}/show`,
|
|
2892
|
+
void 0,
|
|
2893
|
+
storeId ? { storeId } : void 0
|
|
2894
|
+
);
|
|
2895
|
+
}
|
|
2730
2896
|
/**
|
|
2731
2897
|
* Get cross-sell recommendations based on cart contents.
|
|
2732
2898
|
* Returns products that complement items already in the cart.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brainerce",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.25.0",
|
|
4
4
|
"description": "Official SDK for building e-commerce storefronts with Brainerce Platform. Perfect for vibe-coded sites, AI-built stores (Cursor, Lovable, v0), and custom storefronts.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|