@reactionary/provider-commercetools 0.3.11 → 0.3.13
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/core/initialize.js +10 -1
- package/index.js +1 -0
- package/package.json +2 -2
- package/providers/index.js +1 -0
- package/providers/product-reviews.provider.js +183 -0
- package/schema/capabilities.schema.js +1 -0
- package/src/index.d.ts +1 -0
- package/src/providers/index.d.ts +1 -0
- package/src/providers/product-reviews.provider.d.ts +16 -0
- package/src/schema/capabilities.schema.d.ts +2 -1
package/core/initialize.js
CHANGED
|
@@ -16,7 +16,8 @@ import {
|
|
|
16
16
|
CommercetoolsOrderProvider,
|
|
17
17
|
CommercetoolsOrderSearchProvider,
|
|
18
18
|
CommercetoolsProfileProvider,
|
|
19
|
-
CommercetoolsStoreProvider
|
|
19
|
+
CommercetoolsStoreProvider,
|
|
20
|
+
CommercetoolsProductReviewsProvider
|
|
20
21
|
} from "../providers/index.js";
|
|
21
22
|
import { CommercetoolsAPI } from "./client.js";
|
|
22
23
|
function withCommercetoolsCapabilities(configuration, capabilities) {
|
|
@@ -49,6 +50,14 @@ function withCommercetoolsCapabilities(configuration, capabilities) {
|
|
|
49
50
|
commercetoolsApi
|
|
50
51
|
);
|
|
51
52
|
}
|
|
53
|
+
if (caps.productReviews) {
|
|
54
|
+
client.productReviews = new CommercetoolsProductReviewsProvider(
|
|
55
|
+
config,
|
|
56
|
+
cache,
|
|
57
|
+
context,
|
|
58
|
+
commercetoolsApi
|
|
59
|
+
);
|
|
60
|
+
}
|
|
52
61
|
if (caps.identity) {
|
|
53
62
|
client.identity = new CommercetoolsIdentityProvider(
|
|
54
63
|
config,
|
package/index.js
CHANGED
|
@@ -6,6 +6,7 @@ export * from "./providers/inventory.provider.js";
|
|
|
6
6
|
export * from "./providers/order-search.provider.js";
|
|
7
7
|
export * from "./providers/price.provider.js";
|
|
8
8
|
export * from "./providers/product.provider.js";
|
|
9
|
+
export * from "./providers/product-reviews.provider.js";
|
|
9
10
|
export * from "./providers/product-search.provider.js";
|
|
10
11
|
export * from "./schema/capabilities.schema.js";
|
|
11
12
|
export * from "./schema/configuration.schema.js";
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reactionary/provider-commercetools",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.13",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"types": "src/index.d.ts",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@reactionary/core": "0.3.
|
|
7
|
+
"@reactionary/core": "0.3.13",
|
|
8
8
|
"debug": "^4.4.3",
|
|
9
9
|
"zod": "4.1.9",
|
|
10
10
|
"@commercetools/ts-client": "^4.2.1",
|
package/providers/index.js
CHANGED
|
@@ -5,6 +5,7 @@ export * from "./inventory.provider.js";
|
|
|
5
5
|
export * from "./order-search.provider.js";
|
|
6
6
|
export * from "./price.provider.js";
|
|
7
7
|
export * from "./product.provider.js";
|
|
8
|
+
export * from "./product-reviews.provider.js";
|
|
8
9
|
export * from "./profile.provider.js";
|
|
9
10
|
export * from "./product-search.provider.js";
|
|
10
11
|
export * from "./store.provider.js";
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
4
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
5
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
6
|
+
if (decorator = decorators[i])
|
|
7
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
8
|
+
if (kind && result)
|
|
9
|
+
__defProp(target, key, result);
|
|
10
|
+
return result;
|
|
11
|
+
};
|
|
12
|
+
import {
|
|
13
|
+
ProductReviewsProvider,
|
|
14
|
+
Reactionary,
|
|
15
|
+
success,
|
|
16
|
+
error,
|
|
17
|
+
ProductReviewSchema,
|
|
18
|
+
ProductRatingSummarySchema,
|
|
19
|
+
ProductReviewPaginatedResultSchema
|
|
20
|
+
} from "@reactionary/core";
|
|
21
|
+
class CommercetoolsProductReviewsProvider extends ProductReviewsProvider {
|
|
22
|
+
constructor(config, cache, context, commercetools) {
|
|
23
|
+
super(cache, context);
|
|
24
|
+
this.config = config;
|
|
25
|
+
this.commercetools = commercetools;
|
|
26
|
+
}
|
|
27
|
+
async getClient() {
|
|
28
|
+
const client = await this.commercetools.getClient();
|
|
29
|
+
return client.withProjectKey({ projectKey: this.config.projectKey });
|
|
30
|
+
}
|
|
31
|
+
async getAdminClient() {
|
|
32
|
+
const client = await this.commercetools.getAdminClient();
|
|
33
|
+
return client.withProjectKey({ projectKey: this.config.projectKey });
|
|
34
|
+
}
|
|
35
|
+
async getRatingSummary(query) {
|
|
36
|
+
const client = await this.getClient();
|
|
37
|
+
const response = await client.productProjections().withKey({ key: query.product.key }).get().execute().catch((e) => {
|
|
38
|
+
if (e.statusCode === 404) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
throw e;
|
|
42
|
+
});
|
|
43
|
+
if (response && response.body) {
|
|
44
|
+
const summary = {
|
|
45
|
+
identifier: {
|
|
46
|
+
product: query.product
|
|
47
|
+
},
|
|
48
|
+
averageRating: 0,
|
|
49
|
+
totalRatings: 0
|
|
50
|
+
};
|
|
51
|
+
if (response.body.reviewRatingStatistics) {
|
|
52
|
+
summary.averageRating = response.body.reviewRatingStatistics.averageRating;
|
|
53
|
+
summary.totalRatings = response.body.reviewRatingStatistics.count;
|
|
54
|
+
summary.ratingDistribution = {
|
|
55
|
+
"1": response.body.reviewRatingStatistics.ratingsDistribution["1"] ?? 0,
|
|
56
|
+
"2": response.body.reviewRatingStatistics.ratingsDistribution["2"] ?? 0,
|
|
57
|
+
"3": response.body.reviewRatingStatistics.ratingsDistribution["3"] ?? 0,
|
|
58
|
+
"4": response.body.reviewRatingStatistics.ratingsDistribution["4"] ?? 0,
|
|
59
|
+
"5": response.body.reviewRatingStatistics.ratingsDistribution["5"] ?? 0
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
return success(summary);
|
|
63
|
+
} else {
|
|
64
|
+
return success(this.createEmptyProductRatingSummary({ product: query.product }));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
async findReviews(query) {
|
|
68
|
+
const client = await this.getClient();
|
|
69
|
+
const pageNumber = query.paginationOptions?.pageNumber ?? 1;
|
|
70
|
+
const pageSize = query.paginationOptions?.pageSize ?? 20;
|
|
71
|
+
const offset = (pageNumber - 1) * pageSize;
|
|
72
|
+
const product = await client.productProjections().withKey({ key: query.product.key }).get().execute().catch((e) => {
|
|
73
|
+
if (e.statusCode === 404) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
throw e;
|
|
77
|
+
});
|
|
78
|
+
if (!product || !product.body) {
|
|
79
|
+
return success({
|
|
80
|
+
items: [],
|
|
81
|
+
totalCount: 0,
|
|
82
|
+
pageSize,
|
|
83
|
+
pageNumber,
|
|
84
|
+
totalPages: 0
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
const whereClause = `target(typeId="product" and id="${product.body.id}")`;
|
|
88
|
+
const sort = ["createdAt desc"];
|
|
89
|
+
const response = await client.reviews().get({
|
|
90
|
+
queryArgs: {
|
|
91
|
+
where: whereClause,
|
|
92
|
+
limit: pageSize,
|
|
93
|
+
offset,
|
|
94
|
+
sort
|
|
95
|
+
}
|
|
96
|
+
}).execute();
|
|
97
|
+
const reviews = response.body.results.map(
|
|
98
|
+
(review) => this.parseSingle(review, query.product.key)
|
|
99
|
+
);
|
|
100
|
+
const returnedResult = {
|
|
101
|
+
items: reviews,
|
|
102
|
+
totalCount: response.body.total || reviews.length,
|
|
103
|
+
pageSize,
|
|
104
|
+
pageNumber,
|
|
105
|
+
totalPages: Math.ceil((response.body.total || reviews.length) / Math.max(pageSize, 1))
|
|
106
|
+
};
|
|
107
|
+
return success(returnedResult);
|
|
108
|
+
}
|
|
109
|
+
async submitReview(mutation) {
|
|
110
|
+
if (!(this.context.session.identityContext.identity.type === "Registered")) {
|
|
111
|
+
return error({ type: "InvalidInput", error: "Only registered users can submit reviews." });
|
|
112
|
+
}
|
|
113
|
+
const client = await this.getAdminClient();
|
|
114
|
+
const response = await client.reviews().post({
|
|
115
|
+
body: {
|
|
116
|
+
authorName: mutation.authorName,
|
|
117
|
+
title: mutation.title,
|
|
118
|
+
text: mutation.content,
|
|
119
|
+
rating: mutation.rating,
|
|
120
|
+
customer: {
|
|
121
|
+
typeId: "customer",
|
|
122
|
+
id: this.context.session.identityContext.identity.id.userId
|
|
123
|
+
},
|
|
124
|
+
target: {
|
|
125
|
+
typeId: "product",
|
|
126
|
+
id: mutation.product.key
|
|
127
|
+
},
|
|
128
|
+
locale: this.context.languageContext.locale
|
|
129
|
+
}
|
|
130
|
+
}).execute();
|
|
131
|
+
const review = this.parseSingle(response.body, mutation.product.key);
|
|
132
|
+
return success(review);
|
|
133
|
+
}
|
|
134
|
+
parseSingle(review, productKey) {
|
|
135
|
+
return {
|
|
136
|
+
identifier: {
|
|
137
|
+
key: review.key || ""
|
|
138
|
+
},
|
|
139
|
+
product: {
|
|
140
|
+
key: productKey
|
|
141
|
+
},
|
|
142
|
+
authorName: review.authorName ?? "Anonymous",
|
|
143
|
+
authorId: review.customer?.id,
|
|
144
|
+
rating: review.rating ?? 0,
|
|
145
|
+
title: review.title ?? "",
|
|
146
|
+
content: review.text ?? "",
|
|
147
|
+
createdAt: review.createdAt,
|
|
148
|
+
updatedAt: review.lastModifiedAt,
|
|
149
|
+
verified: !!review.customer
|
|
150
|
+
// Verified if linked to a customer
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
__decorateClass([
|
|
155
|
+
Reactionary({
|
|
156
|
+
outputSchema: ProductRatingSummarySchema,
|
|
157
|
+
cache: true,
|
|
158
|
+
cacheTimeToLiveInSeconds: 300,
|
|
159
|
+
currencyDependentCaching: false,
|
|
160
|
+
localeDependentCaching: false
|
|
161
|
+
})
|
|
162
|
+
], CommercetoolsProductReviewsProvider.prototype, "getRatingSummary", 1);
|
|
163
|
+
__decorateClass([
|
|
164
|
+
Reactionary({
|
|
165
|
+
outputSchema: ProductReviewPaginatedResultSchema,
|
|
166
|
+
cache: true,
|
|
167
|
+
cacheTimeToLiveInSeconds: 60,
|
|
168
|
+
currencyDependentCaching: false,
|
|
169
|
+
localeDependentCaching: true
|
|
170
|
+
})
|
|
171
|
+
], CommercetoolsProductReviewsProvider.prototype, "findReviews", 1);
|
|
172
|
+
__decorateClass([
|
|
173
|
+
Reactionary({
|
|
174
|
+
outputSchema: ProductReviewSchema,
|
|
175
|
+
cache: false,
|
|
176
|
+
cacheTimeToLiveInSeconds: 0,
|
|
177
|
+
currencyDependentCaching: false,
|
|
178
|
+
localeDependentCaching: false
|
|
179
|
+
})
|
|
180
|
+
], CommercetoolsProductReviewsProvider.prototype, "submitReview", 1);
|
|
181
|
+
export {
|
|
182
|
+
CommercetoolsProductReviewsProvider
|
|
183
|
+
};
|
package/src/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export * from './providers/inventory.provider.js';
|
|
|
6
6
|
export * from './providers/order-search.provider.js';
|
|
7
7
|
export * from './providers/price.provider.js';
|
|
8
8
|
export * from './providers/product.provider.js';
|
|
9
|
+
export * from './providers/product-reviews.provider.js';
|
|
9
10
|
export * from './providers/product-search.provider.js';
|
|
10
11
|
export * from './schema/capabilities.schema.js';
|
|
11
12
|
export * from './schema/configuration.schema.js';
|
package/src/providers/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export * from './inventory.provider.js';
|
|
|
5
5
|
export * from './order-search.provider.js';
|
|
6
6
|
export * from './price.provider.js';
|
|
7
7
|
export * from './product.provider.js';
|
|
8
|
+
export * from './product-reviews.provider.js';
|
|
8
9
|
export * from './profile.provider.js';
|
|
9
10
|
export * from './product-search.provider.js';
|
|
10
11
|
export * from './store.provider.js';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ProductReviewsProvider } from '@reactionary/core';
|
|
2
|
+
import type { ProductReview, ProductRatingSummary, ProductReviewPaginatedResult, ProductReviewsListQuery, ProductReviewsGetRatingSummaryQuery, ProductReviewMutationSubmit, Result, RequestContext, Cache } from '@reactionary/core';
|
|
3
|
+
import type { CommercetoolsConfiguration } from '../schema/configuration.schema.js';
|
|
4
|
+
import type { CommercetoolsAPI } from '../core/client.js';
|
|
5
|
+
import type { Review as CTReview } from '@commercetools/platform-sdk';
|
|
6
|
+
export declare class CommercetoolsProductReviewsProvider extends ProductReviewsProvider {
|
|
7
|
+
protected config: CommercetoolsConfiguration;
|
|
8
|
+
protected commercetools: CommercetoolsAPI;
|
|
9
|
+
constructor(config: CommercetoolsConfiguration, cache: Cache, context: RequestContext, commercetools: CommercetoolsAPI);
|
|
10
|
+
protected getClient(): Promise<import("@commercetools/platform-sdk").ByProjectKeyRequestBuilder>;
|
|
11
|
+
protected getAdminClient(): Promise<import("@commercetools/platform-sdk").ByProjectKeyRequestBuilder>;
|
|
12
|
+
getRatingSummary(query: ProductReviewsGetRatingSummaryQuery): Promise<Result<ProductRatingSummary>>;
|
|
13
|
+
findReviews(query: ProductReviewsListQuery): Promise<Result<ProductReviewPaginatedResult>>;
|
|
14
|
+
submitReview(mutation: ProductReviewMutationSubmit): Promise<Result<ProductReview>>;
|
|
15
|
+
protected parseSingle(review: CTReview, productKey: string): ProductReview;
|
|
16
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type * as z from 'zod';
|
|
2
2
|
export declare const CommercetoolsCapabilitiesSchema: z.ZodObject<{
|
|
3
|
-
price: z.ZodOptional<z.ZodBoolean>;
|
|
4
3
|
product: z.ZodOptional<z.ZodBoolean>;
|
|
4
|
+
price: z.ZodOptional<z.ZodBoolean>;
|
|
5
5
|
order: z.ZodOptional<z.ZodBoolean>;
|
|
6
6
|
cart: z.ZodOptional<z.ZodBoolean>;
|
|
7
7
|
checkout: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -11,6 +11,7 @@ export declare const CommercetoolsCapabilitiesSchema: z.ZodObject<{
|
|
|
11
11
|
profile: z.ZodOptional<z.ZodBoolean>;
|
|
12
12
|
store: z.ZodOptional<z.ZodBoolean>;
|
|
13
13
|
productSearch: z.ZodOptional<z.ZodBoolean>;
|
|
14
|
+
productReviews: z.ZodOptional<z.ZodBoolean>;
|
|
14
15
|
orderSearch: z.ZodOptional<z.ZodBoolean>;
|
|
15
16
|
}, z.core.$loose>;
|
|
16
17
|
export type CommercetoolsCapabilities = z.infer<typeof CommercetoolsCapabilitiesSchema>;
|