Skip to content

Commit c685925

Browse files
Afstklaclaude
andcommitted
Address PR feedback: Update dependencies, improve code quality, and follow best practices
- Update @pipedream/platform to ^3.1.0 - Add authentication validation in _getAuthHeaders - Extract common review fetching logic to reduce duplication (DRY) - Remove unnecessary try/catch from _makeRequest - Use ConfigurationError for user input errors - Remove publishedAt from all components - Update polling descriptions to be more generic - Improve code maintainability and error handling Co-Authored-By: Claude <[email protected]>
1 parent 404d68f commit c685925

File tree

16 files changed

+63
-117
lines changed

16 files changed

+63
-117
lines changed

components/trustpilot/actions/fetch-product-review-by-id/fetch-product-review-by-id.mjs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ export default {
55
name: "Fetch Product Review by ID",
66
description: "Retrieves detailed information about a specific product review on Trustpilot. Use this action to get comprehensive data about a single product review, including customer feedback, star rating, review text, and metadata. Perfect for analyzing individual customer experiences, responding to specific feedback, or integrating review data into your customer service workflows. [See the documentation](https://developers.trustpilot.com/product-reviews-api#get-private-product-review)",
77
version: "0.0.1",
8-
publishedAt: "2025-07-18T00:00:00.000Z",
98
type: "action",
109
props: {
1110
trustpilot,

components/trustpilot/actions/fetch-product-reviews/fetch-product-reviews.mjs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ export default {
55
name: "Fetch Product Reviews",
66
description: "Retrieves a list of product reviews for a specific business unit on Trustpilot. This action enables you to fetch multiple product reviews with powerful filtering options including star ratings, language, tags, and sorting preferences. Ideal for monitoring product feedback trends, generating reports, analyzing customer sentiment across your product catalog, or building review dashboards. Supports pagination for handling large review volumes. [See the documentation](https://developers.trustpilot.com/product-reviews-api#get-private-product-reviews)",
77
version: "0.0.1",
8-
publishedAt: "2025-07-18T00:00:00.000Z",
98
type: "action",
109
props: {
1110
trustpilot,

components/trustpilot/actions/fetch-service-review-by-id/fetch-service-review-by-id.mjs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ export default {
55
name: "Fetch Service Review by ID",
66
description: "Retrieves detailed information about a specific service review for your business on Trustpilot. Use this action to access comprehensive data about an individual service review, including the customer's rating, review content, date, and any responses. Essential for customer service teams to analyze specific feedback, track review history, or integrate individual review data into CRM systems and support tickets. [See the documentation](https://developers.trustpilot.com/business-units-api#get-business-unit-review)",
77
version: "0.0.1",
8-
publishedAt: "2025-07-18T00:00:00.000Z",
98
type: "action",
109
props: {
1110
trustpilot,

components/trustpilot/actions/fetch-service-reviews/fetch-service-reviews.mjs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ export default {
66
description: "Fetches service reviews for a specific business unit from Trustpilot with support for filtering by star rating, tags, language, and more. [See the documentation](https://developers.trustpilot.com/business-units-api#get-business-unit-reviews)",
77
version: "0.0.1",
88
type: "action",
9-
publishedAt: "2025-07-18T00:00:00.000Z",
109
props: {
1110
trustpilot,
1211
businessUnitId: {
Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import trustpilot from "../../app/trustpilot.app.ts";
2+
import { ConfigurationError } from "@pipedream/platform";
23

34
export default {
45
key: "trustpilot-reply-to-product-review",
56
name: "Reply to Product Review",
67
description: "Posts a public reply to a product review on Trustpilot on behalf of your business. This action allows you to respond to customer feedback, address concerns, thank customers for positive reviews, or provide additional information about products. Replies help demonstrate your commitment to customer satisfaction and can improve your overall reputation. Note that replies are publicly visible and cannot be edited once posted. [See the documentation](https://developers.trustpilot.com/product-reviews-api#reply-to-product-review)",
78
version: "0.0.1",
8-
publishedAt: "2025-07-18T00:00:00.000Z",
99
type: "action",
1010
props: {
1111
trustpilot,
@@ -28,28 +28,24 @@ export default {
2828
} = this;
2929

3030
if (!message || message.trim().length === 0) {
31-
throw new Error("Reply message cannot be empty");
31+
throw new ConfigurationError("Reply message cannot be empty");
3232
}
3333

34-
try {
35-
const result = await this.trustpilot.replyToProductReview({
36-
reviewId,
37-
message: message.trim(),
38-
});
34+
const result = await this.trustpilot.replyToProductReview({
35+
reviewId,
36+
message: message.trim(),
37+
});
3938

40-
$.export("$summary", `Successfully replied to product review ${reviewId}`);
39+
$.export("$summary", `Successfully replied to product review ${reviewId}`);
4140

42-
return {
43-
success: true,
44-
reply: result,
45-
metadata: {
46-
reviewId,
47-
messageLength: message.trim().length,
48-
requestTime: new Date().toISOString(),
49-
},
50-
};
51-
} catch (error) {
52-
throw new Error(`Failed to reply to product review: ${error.message}`);
53-
}
41+
return {
42+
success: true,
43+
reply: result,
44+
metadata: {
45+
reviewId,
46+
messageLength: message.trim().length,
47+
requestTime: new Date().toISOString(),
48+
},
49+
};
5450
},
5551
};
Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import trustpilot from "../../app/trustpilot.app.ts";
2+
import { ConfigurationError } from "@pipedream/platform";
23

34
export default {
45
key: "trustpilot-reply-to-service-review",
56
name: "Reply to Service Review",
67
description: "Posts a public reply to a service review on Trustpilot on behalf of your business. This action enables you to engage with customers who have reviewed your services, allowing you to address complaints, clarify misunderstandings, express gratitude for positive feedback, or provide updates on how you're improving based on their input. Professional responses to reviews can significantly impact your business reputation and show potential customers that you value feedback. Remember that all replies are permanent and publicly visible. [See the documentation](https://developers.trustpilot.com/business-units-api#reply-to-review)",
78
version: "0.0.1",
8-
publishedAt: "2025-07-18T00:00:00.000Z",
99
type: "action",
1010
props: {
1111
trustpilot,
@@ -35,30 +35,26 @@ export default {
3535
} = this;
3636

3737
if (!message || message.trim().length === 0) {
38-
throw new Error("Reply message cannot be empty");
38+
throw new ConfigurationError("Reply message cannot be empty");
3939
}
4040

41-
try {
42-
const result = await this.trustpilot.replyToServiceReview({
43-
businessUnitId,
44-
reviewId,
45-
message: message.trim(),
46-
});
41+
const result = await this.trustpilot.replyToServiceReview({
42+
businessUnitId,
43+
reviewId,
44+
message: message.trim(),
45+
});
4746

48-
$.export("$summary", `Successfully replied to service review ${reviewId}`);
47+
$.export("$summary", `Successfully replied to service review ${reviewId}`);
4948

50-
return {
51-
success: true,
52-
reply: result,
53-
metadata: {
54-
businessUnitId,
55-
reviewId,
56-
messageLength: message.trim().length,
57-
requestTime: new Date().toISOString(),
58-
},
59-
};
60-
} catch (error) {
61-
throw new Error(`Failed to reply to service review: ${error.message}`);
62-
}
49+
return {
50+
success: true,
51+
reply: result,
52+
metadata: {
53+
businessUnitId,
54+
reviewId,
55+
messageLength: message.trim().length,
56+
requestTime: new Date().toISOString(),
57+
},
58+
};
6359
},
6460
};

components/trustpilot/app/trustpilot.app.ts

Lines changed: 20 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { defineApp } from "@pipedream/types";
2-
import { axios } from "@pipedream/platform";
2+
import { axios, ConfigurationError } from "@pipedream/platform";
33
import crypto from "crypto";
44
import {
55
BASE_URL,
@@ -108,6 +108,10 @@ export default defineApp({
108108
"User-Agent": "Pipedream/1.0",
109109
};
110110

111+
if (!this.$auth?.api_key && !this.$auth?.oauth_access_token) {
112+
throw new Error("Authentication required: Configure either API key or OAuth token");
113+
}
114+
111115
if (this.$auth?.api_key) {
112116
headers["apikey"] = this.$auth.api_key;
113117
}
@@ -136,13 +140,8 @@ export default defineApp({
136140
config.data = data;
137141
}
138142

139-
try {
140-
const response = await axios(this, config);
141-
return response.data || response;
142-
} catch (error) {
143-
const parsedError = parseApiError(error);
144-
throw new Error(`Trustpilot API Error: ${parsedError.message} (${parsedError.code})`);
145-
}
143+
const response = await axios(this, config);
144+
return response.data || response;
146145
},
147146

148147
async _makeRequestWithRetry(config, retries = RETRY_CONFIG.MAX_RETRIES) {
@@ -238,8 +237,9 @@ export default defineApp({
238237
return parseReview(response);
239238
},
240239

241-
// Private Service Review methods
242-
async getServiceReviews({
240+
// Private helper for fetching reviews
241+
async _getReviews({
242+
endpoint,
243243
businessUnitId,
244244
stars = null,
245245
sortBy = SORT_OPTIONS.CREATED_AT_DESC,
@@ -249,11 +249,10 @@ export default defineApp({
249249
tags = [],
250250
language = null,
251251
} = {}) {
252-
if (!validateBusinessUnitId(businessUnitId)) {
252+
if (businessUnitId && !validateBusinessUnitId(businessUnitId)) {
253253
throw new Error("Invalid business unit ID");
254254
}
255255

256-
const endpoint = buildUrl(ENDPOINTS.PRIVATE_SERVICE_REVIEWS, { businessUnitId });
257256
const params = {
258257
stars,
259258
orderBy: sortBy,
@@ -283,6 +282,12 @@ export default defineApp({
283282
};
284283
},
285284

285+
// Private Service Review methods
286+
async getServiceReviews(options = {}) {
287+
const endpoint = buildUrl(ENDPOINTS.PRIVATE_SERVICE_REVIEWS, { businessUnitId: options.businessUnitId });
288+
return this._getReviews({ endpoint, ...options });
289+
},
290+
286291
async getServiceReviewById({ businessUnitId, reviewId }) {
287292
if (!validateBusinessUnitId(businessUnitId)) {
288293
throw new Error("Invalid business unit ID");
@@ -326,48 +331,9 @@ export default defineApp({
326331
},
327332

328333
// Product Review methods
329-
async getProductReviews({
330-
businessUnitId,
331-
stars = null,
332-
sortBy = SORT_OPTIONS.CREATED_AT_DESC,
333-
limit = DEFAULT_LIMIT,
334-
offset = 0,
335-
includeReportedReviews = false,
336-
tags = [],
337-
language = null,
338-
} = {}) {
339-
if (!validateBusinessUnitId(businessUnitId)) {
340-
throw new Error("Invalid business unit ID");
341-
}
342-
343-
const endpoint = buildUrl(ENDPOINTS.PRIVATE_PRODUCT_REVIEWS, { businessUnitId });
344-
const params = {
345-
stars,
346-
orderBy: sortBy,
347-
perPage: limit,
348-
page: Math.floor(offset / limit) + 1,
349-
includeReportedReviews,
350-
language,
351-
};
352-
353-
if (tags.length > 0) {
354-
params.tags = tags.join(",");
355-
}
356-
357-
const response = await this._makeRequestWithRetry({
358-
endpoint,
359-
params,
360-
});
361-
362-
return {
363-
reviews: response.reviews?.map(parseReview) || [],
364-
pagination: {
365-
total: response.pagination?.total || 0,
366-
page: response.pagination?.page || 1,
367-
perPage: response.pagination?.perPage || limit,
368-
hasMore: response.pagination?.hasMore || false,
369-
},
370-
};
334+
async getProductReviews(options = {}) {
335+
const endpoint = buildUrl(ENDPOINTS.PRIVATE_PRODUCT_REVIEWS, { businessUnitId: options.businessUnitId });
336+
return this._getReviews({ endpoint, ...options });
371337
},
372338

373339
async getProductReviewById({ reviewId }) {

components/trustpilot/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@
1414
"access": "public"
1515
},
1616
"dependencies": {
17-
"@pipedream/platform": "^3.0.0"
17+
"@pipedream/platform": "^3.1.0"
1818
}
1919
}

components/trustpilot/sources/new-conversations/new-conversations.mjs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,8 @@ export default {
77
...common,
88
key: "trustpilot-new-conversations",
99
name: "New Conversations",
10-
description: "Emit new event when a new conversation is started on Trustpilot. This source polls the Trustpilot API every 15 minutes to detect new customer-business conversations. Each event contains conversation details including participants, subject, business unit, and creation timestamp. Useful for tracking customer inquiries, support requests, and maintaining real-time communication with customers.",
10+
description: "Emit new event when a new conversation is started on Trustpilot. This source periodically polls the Trustpilot API to detect new customer-business conversations. Each event contains conversation details including participants, subject, business unit, and creation timestamp. Useful for tracking customer inquiries, support requests, and maintaining real-time communication with customers.",
1111
version: "0.0.1",
12-
publishedAt: "2025-07-18T00:00:00.000Z",
1312
type: "source",
1413
dedupe: "unique",
1514
methods: {

components/trustpilot/sources/new-product-review-replies/new-product-review-replies.mjs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,8 @@ export default {
77
...common,
88
key: "trustpilot-new-product-review-replies",
99
name: "New Product Review Replies",
10-
description: "Emit new event when a business replies to a product review on Trustpilot. This source polls the Trustpilot API every 15 minutes to detect new replies to product reviews. Each event includes the reply text, creation timestamp, and associated review details (product name, star rating, consumer info). Ideal for monitoring business responses to customer feedback, tracking customer service performance, and ensuring timely engagement with product reviews.",
10+
description: "Emit new event when a business replies to a product review on Trustpilot. This source periodically polls the Trustpilot API to detect new replies to product reviews. Each event includes the reply text, creation timestamp, and associated review details (product name, star rating, consumer info). Ideal for monitoring business responses to customer feedback, tracking customer service performance, and ensuring timely engagement with product reviews.",
1111
version: "0.0.1",
12-
publishedAt: "2025-07-18T00:00:00.000Z",
1312
type: "source",
1413
dedupe: "unique",
1514
methods: {

0 commit comments

Comments
 (0)