@reactionary/provider-commercetools 0.3.10 → 0.3.12

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.
@@ -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.10",
3
+ "version": "0.3.12",
4
4
  "main": "index.js",
5
5
  "types": "src/index.d.ts",
6
6
  "dependencies": {
7
- "@reactionary/core": "0.3.10",
7
+ "@reactionary/core": "0.3.12",
8
8
  "debug": "^4.4.3",
9
9
  "zod": "4.1.9",
10
10
  "@commercetools/ts-client": "^4.2.1",
@@ -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,169 @@
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
+ } from "@reactionary/core";
20
+ class CommercetoolsProductReviewsProvider extends ProductReviewsProvider {
21
+ constructor(config, cache, context, commercetools) {
22
+ super(cache, context);
23
+ this.config = config;
24
+ this.commercetools = commercetools;
25
+ }
26
+ async getClient() {
27
+ const client = await this.commercetools.getClient();
28
+ return client.withProjectKey({ projectKey: this.config.projectKey });
29
+ }
30
+ async getAdminClient() {
31
+ const client = await this.commercetools.getAdminClient();
32
+ return client.withProjectKey({ projectKey: this.config.projectKey });
33
+ }
34
+ async getRatingSummary(query) {
35
+ const client = await this.getClient();
36
+ const response = await client.productProjections().withKey({ key: query.product.key }).get().execute().catch((e) => {
37
+ if (e.statusCode === 404) {
38
+ return null;
39
+ }
40
+ throw e;
41
+ });
42
+ if (response && response.body) {
43
+ const summary = {
44
+ identifier: {
45
+ product: query.product
46
+ },
47
+ averageRating: 0,
48
+ totalRatings: 0
49
+ };
50
+ if (response.body.reviewRatingStatistics) {
51
+ summary.averageRating = response.body.reviewRatingStatistics.averageRating;
52
+ summary.totalRatings = response.body.reviewRatingStatistics.count;
53
+ summary.ratingDistribution = {
54
+ "1": response.body.reviewRatingStatistics.ratingsDistribution["1"] ?? 0,
55
+ "2": response.body.reviewRatingStatistics.ratingsDistribution["2"] ?? 0,
56
+ "3": response.body.reviewRatingStatistics.ratingsDistribution["3"] ?? 0,
57
+ "4": response.body.reviewRatingStatistics.ratingsDistribution["4"] ?? 0,
58
+ "5": response.body.reviewRatingStatistics.ratingsDistribution["5"] ?? 0
59
+ };
60
+ }
61
+ return success(summary);
62
+ } else {
63
+ return error({ type: "NotFound", identifier: query.product });
64
+ }
65
+ }
66
+ async listReviews(query) {
67
+ const client = await this.getClient();
68
+ const pageNumber = query.paginationOptions?.pageNumber ?? 1;
69
+ const pageSize = query.paginationOptions?.pageSize ?? 20;
70
+ const offset = (pageNumber - 1) * pageSize;
71
+ const product = await client.productProjections().withKey({ key: query.product.key }).get().execute().catch((e) => {
72
+ if (e.statusCode === 404) {
73
+ return null;
74
+ }
75
+ throw e;
76
+ });
77
+ if (!product || !product.body) {
78
+ return error({ type: "NotFound", identifier: query.product });
79
+ }
80
+ const whereClause = `target(typeId="product" and id="${product.body.id}")`;
81
+ const sort = ["createdAt desc"];
82
+ const response = await client.reviews().get({
83
+ queryArgs: {
84
+ where: whereClause,
85
+ limit: pageSize,
86
+ offset,
87
+ sort
88
+ }
89
+ }).execute();
90
+ const reviews = response.body.results.map(
91
+ (review) => this.parseSingle(review, query.product.key)
92
+ );
93
+ return success(reviews);
94
+ }
95
+ async submitReview(mutation) {
96
+ if (!(this.context.session.identityContext.identity.type === "Registered")) {
97
+ return error({ type: "InvalidInput", error: "Only registered users can submit reviews." });
98
+ }
99
+ const client = await this.getAdminClient();
100
+ const response = await client.reviews().post({
101
+ body: {
102
+ authorName: mutation.authorName,
103
+ title: mutation.title,
104
+ text: mutation.content,
105
+ rating: mutation.rating,
106
+ customer: {
107
+ typeId: "customer",
108
+ id: this.context.session.identityContext.identity.id.userId
109
+ },
110
+ target: {
111
+ typeId: "product",
112
+ id: mutation.product.key
113
+ },
114
+ locale: this.context.languageContext.locale
115
+ }
116
+ }).execute();
117
+ const review = this.parseSingle(response.body, mutation.product.key);
118
+ return success(review);
119
+ }
120
+ parseSingle(review, productKey) {
121
+ return {
122
+ identifier: {
123
+ key: review.key || ""
124
+ },
125
+ product: {
126
+ key: productKey
127
+ },
128
+ authorName: review.authorName ?? "Anonymous",
129
+ authorId: review.customer?.id,
130
+ rating: review.rating ?? 0,
131
+ title: review.title ?? "",
132
+ content: review.text ?? "",
133
+ createdAt: review.createdAt,
134
+ updatedAt: review.lastModifiedAt,
135
+ verified: !!review.customer
136
+ // Verified if linked to a customer
137
+ };
138
+ }
139
+ }
140
+ __decorateClass([
141
+ Reactionary({
142
+ outputSchema: ProductRatingSummarySchema,
143
+ cache: true,
144
+ cacheTimeToLiveInSeconds: 300,
145
+ currencyDependentCaching: false,
146
+ localeDependentCaching: false
147
+ })
148
+ ], CommercetoolsProductReviewsProvider.prototype, "getRatingSummary", 1);
149
+ __decorateClass([
150
+ Reactionary({
151
+ outputSchema: ProductReviewSchema.array(),
152
+ cache: true,
153
+ cacheTimeToLiveInSeconds: 60,
154
+ currencyDependentCaching: false,
155
+ localeDependentCaching: true
156
+ })
157
+ ], CommercetoolsProductReviewsProvider.prototype, "listReviews", 1);
158
+ __decorateClass([
159
+ Reactionary({
160
+ outputSchema: ProductReviewSchema,
161
+ cache: false,
162
+ cacheTimeToLiveInSeconds: 0,
163
+ currencyDependentCaching: false,
164
+ localeDependentCaching: false
165
+ })
166
+ ], CommercetoolsProductReviewsProvider.prototype, "submitReview", 1);
167
+ export {
168
+ CommercetoolsProductReviewsProvider
169
+ };
@@ -2,6 +2,7 @@ import { CapabilitiesSchema } from "@reactionary/core";
2
2
  const CommercetoolsCapabilitiesSchema = CapabilitiesSchema.pick({
3
3
  product: true,
4
4
  productSearch: true,
5
+ productReviews: true,
5
6
  identity: true,
6
7
  cart: true,
7
8
  checkout: true,
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';
@@ -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, 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
+ listReviews(query: ProductReviewsListQuery): Promise<Result<ProductReview[]>>;
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>;