@reactionary/provider-commercetools 0.0.59 → 0.0.61

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 CHANGED
@@ -1,6 +1,33 @@
1
- # provider-commercetools
1
+ # Commmercetools provider for Reactionary
2
+
3
+ ## Supports
4
+
5
+
6
+ | Feature | Support | Notes |
7
+ | ----------- | ----------- | --------- |
8
+ | product | Full | |
9
+ | productSearch | Full | |
10
+ | identity | Full | |
11
+ | cart | Full | |
12
+ | checkout | Full | |
13
+ | order | Full | |
14
+ | inventory | Full | |
15
+ | price | Full | |
16
+ | category | Full | |
17
+ | store | Full | |
18
+
19
+
20
+ ## Notes
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
2
30
 
3
- This library was generated with [Nx](https://nx.dev).
4
31
 
5
32
  ## Building
6
33
 
@@ -11,7 +38,7 @@ Run `nx build provider-commercetools` to build the library.
11
38
  Run `nx test provider-commercetools` to execute the unit tests via [Jest](https://jestjs.io).
12
39
 
13
40
 
14
- # ASSUMPTIONS for backend config
41
+ ## Assumptions for backend config
15
42
 
16
43
  - You will have 2 different channels for prices, one called `Offer Price` and one called `List Price`
17
44
  - ProductVariants will all have unique SKU values.
package/core/client.js CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  } from "@reactionary/core";
11
11
  import * as crypto from "crypto";
12
12
  import createDebug from "debug";
13
- const debug = createDebug("commercetools:debug");
13
+ const debug = createDebug("reactionary:commercetools");
14
14
  class RequestContextTokenCache {
15
15
  constructor(context) {
16
16
  this.context = context;
@@ -4,11 +4,12 @@ import {
4
4
  InventorySchema,
5
5
  PriceSchema,
6
6
  ProductSchema,
7
- SearchResultSchema,
7
+ ProductSearchResultSchema,
8
8
  CategorySchema,
9
- CheckoutSchema
9
+ CheckoutSchema,
10
+ ProductSearchResultItemSchema
10
11
  } from "@reactionary/core";
11
- import { CommercetoolsSearchProvider } from "../providers/search.provider.js";
12
+ import { CommercetoolsSearchProvider } from "../providers/product-search.provider.js";
12
13
  import { CommercetoolsProductProvider } from "../providers/product.provider.js";
13
14
  import { CommercetoolsIdentityProvider } from "../providers/identity.provider.js";
14
15
  import { CommercetoolsCartProvider } from "../providers/cart.provider.js";
@@ -22,8 +23,8 @@ function withCommercetoolsCapabilities(configuration, capabilities) {
22
23
  if (capabilities.product) {
23
24
  client.product = new CommercetoolsProductProvider(configuration, ProductSchema, cache);
24
25
  }
25
- if (capabilities.search) {
26
- client.search = new CommercetoolsSearchProvider(configuration, SearchResultSchema, cache);
26
+ if (capabilities.productSearch) {
27
+ client.productSearch = new CommercetoolsSearchProvider(configuration, ProductSearchResultItemSchema, cache);
27
28
  }
28
29
  if (capabilities.identity) {
29
30
  client.identity = new CommercetoolsIdentityProvider(configuration, IdentitySchema, cache);
package/index.js CHANGED
@@ -5,6 +5,6 @@ export * from "./providers/identity.provider.js";
5
5
  export * from "./providers/inventory.provider.js";
6
6
  export * from "./providers/price.provider.js";
7
7
  export * from "./providers/product.provider.js";
8
- export * from "./providers/search.provider.js";
8
+ export * from "./providers/product-search.provider.js";
9
9
  export * from "./schema/capabilities.schema.js";
10
10
  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.0.59",
3
+ "version": "0.0.61",
4
4
  "main": "index.js",
5
5
  "types": "src/index.d.ts",
6
6
  "dependencies": {
7
- "@reactionary/core": "0.0.59",
7
+ "@reactionary/core": "0.0.61",
8
8
  "debug": "^4.4.3",
9
9
  "zod": "4.1.9",
10
10
  "@commercetools/ts-client": "^4.2.1",
@@ -34,7 +34,7 @@ class CommercetoolsCartProvider extends CartProvider {
34
34
  {
35
35
  action: "addLineItem",
36
36
  quantity: payload.quantity,
37
- sku: payload.sku.key
37
+ sku: payload.variant.sku
38
38
  },
39
39
  {
40
40
  action: "recalculate"
@@ -346,7 +346,7 @@ class CommercetoolsCartProvider extends CartProvider {
346
346
  const item = CartItemSchema.parse({});
347
347
  item.identifier.key = remoteItem.id;
348
348
  item.product.key = remoteItem.productId;
349
- item.sku.key = remoteItem.variant.sku || "";
349
+ item.variant.sku = remoteItem.variant.sku || "";
350
350
  item.quantity = remoteItem.quantity;
351
351
  const unitPrice = remoteItem.price.value.centAmount;
352
352
  const totalPrice = remoteItem.totalPrice.centAmount || 0;
@@ -378,7 +378,7 @@ class CommercetoolsCheckoutProvider extends CheckoutProvider {
378
378
  for (const remoteItem of remote.lineItems) {
379
379
  const item = CheckoutItemSchema.parse({});
380
380
  item.identifier.key = remoteItem.id;
381
- item.sku.key = remoteItem.variant.sku || "";
381
+ item.variant.sku = remoteItem.variant.sku || "";
382
382
  item.quantity = remoteItem.quantity;
383
383
  const unitPrice = remoteItem.price.value.centAmount;
384
384
  const totalPrice = remoteItem.totalPrice.centAmount || 0;
@@ -5,7 +5,7 @@ export * from "./inventory.provider.js";
5
5
  export * from "./price.provider.js";
6
6
  export * from "./product.provider.js";
7
7
  export * from "./profile.provider.js";
8
- export * from "./search.provider.js";
8
+ export * from "./product-search.provider.js";
9
9
  export * from "./store.provider.js";
10
10
  export * from "./order.provider.js";
11
11
  export * from "./checkout.provider.js";
@@ -16,7 +16,7 @@ class CommercetoolsInventoryProvider extends InventoryProvider {
16
16
  const remote = await client.withProjectKey({ projectKey: this.config.projectKey }).inventory().get({
17
17
  queryArgs: {
18
18
  where: "sku=:sku AND supplyChannel(id=:channel)",
19
- "var.sku": payload.sku.key,
19
+ "var.sku": payload.variant.sku,
20
20
  "var.channel": channelId,
21
21
  expand: "supplyChannel"
22
22
  }
@@ -28,7 +28,7 @@ class CommercetoolsInventoryProvider extends InventoryProvider {
28
28
  parseSingle(body, reqCtx) {
29
29
  const model = this.newModel();
30
30
  model.identifier = {
31
- sku: { key: body.sku || "" },
31
+ variant: { sku: body.sku || "" },
32
32
  fulfillmentCenter: {
33
33
  key: body.supplyChannel?.obj?.key || ""
34
34
  }
@@ -77,7 +77,7 @@ class CommercetoolsOrderProvider extends OrderProvider {
77
77
  for (const remoteItem of remote.lineItems) {
78
78
  const item = OrderItemSchema.parse({});
79
79
  item.identifier.key = remoteItem.id;
80
- item.sku.key = remoteItem.variant.sku || "";
80
+ item.variant.sku = remoteItem.variant.sku || "";
81
81
  item.quantity = remoteItem.quantity;
82
82
  const unitPrice = remoteItem.price.value.centAmount;
83
83
  const totalPrice = remoteItem.totalPrice.centAmount || 0;
@@ -23,16 +23,16 @@ class CommercetoolsPriceProvider extends PriceProvider {
23
23
  priceCurrency: reqCtx.languageContext.currencyCode,
24
24
  // storeProjection: reqCtx.storeIdentifier?.key || undefined,
25
25
  where: "variants(sku in (:skus)) OR (masterVariant(sku in (:skus))) ",
26
- "var.skus": payload.map((p) => p.sku.key),
26
+ "var.skus": payload.map((p) => p.variant.sku),
27
27
  limit: payload.length
28
28
  }
29
29
  }).execute();
30
30
  const result = [];
31
31
  const allReturnedVariants = [...response.body.results.map((x) => x.variants).flat(), ...response.body.results.map((x) => x.masterVariant).flat()];
32
32
  for (const p of payload) {
33
- const foundSku = allReturnedVariants.find((v) => v.sku === p.sku.key);
33
+ const foundSku = allReturnedVariants.find((v) => v.sku === p.variant.sku);
34
34
  if (!foundSku) {
35
- result.push(this.createEmptyPriceResult(p.sku.key, reqCtx.languageContext.currencyCode));
35
+ result.push(this.createEmptyPriceResult(p.variant.sku, reqCtx.languageContext.currencyCode));
36
36
  } else {
37
37
  result.push(this.parseSingle(foundSku, reqCtx));
38
38
  }
@@ -66,8 +66,8 @@ class CommercetoolsPriceProvider extends PriceProvider {
66
66
  base.tieredPrices = p;
67
67
  }
68
68
  base.identifier = {
69
- sku: {
70
- key: body.sku
69
+ variant: {
70
+ sku: body.sku
71
71
  }
72
72
  };
73
73
  base.meta = {
@@ -0,0 +1,123 @@
1
+ import { createPaginatedResponseSchema, FacetIdentifierSchema, FacetValueIdentifierSchema, ImageSchema, ProductOptionIdentifierSchema, ProductSearchProvider, ProductSearchResultFacetSchema, ProductSearchResultFacetValueSchema, ProductSearchResultItemVariantSchema, ProductVariantIdentifierSchema, ProductVariantOptionSchema } from "@reactionary/core";
2
+ import { CommercetoolsClient } from "../core/client.js";
3
+ import createDebug from "debug";
4
+ const debug = createDebug("reactionary:commercetools:search");
5
+ class CommercetoolsSearchProvider extends ProductSearchProvider {
6
+ constructor(config, schema, cache) {
7
+ super(schema, cache);
8
+ this.config = config;
9
+ }
10
+ async getClient(reqCtx) {
11
+ const client = await new CommercetoolsClient(this.config).getClient(reqCtx);
12
+ return client.withProjectKey({ projectKey: this.config.projectKey }).productProjections();
13
+ }
14
+ async queryByTerm(payload, reqCtx) {
15
+ const client = await this.getClient(reqCtx);
16
+ const response = await client.search().get({
17
+ queryArgs: {
18
+ limit: payload.search.paginationOptions.pageSize,
19
+ offset: (payload.search.paginationOptions.pageNumber - 1) * payload.search.paginationOptions.pageSize,
20
+ [`text.${reqCtx.languageContext.locale}`]: payload.search.term
21
+ }
22
+ }).execute();
23
+ const responseBody = response.body;
24
+ const result = this.parsePaginatedResult(responseBody, reqCtx);
25
+ if (debug.enabled) {
26
+ debug(`Search for term "${payload.search.term}" returned ${responseBody.results.length} products (page ${payload.search.paginationOptions.pageNumber} of ${result.totalPages})`);
27
+ }
28
+ result.identifier = {
29
+ ...payload.search
30
+ };
31
+ result.meta = {
32
+ cache: { hit: false, key: "" },
33
+ placeholder: false
34
+ };
35
+ return result;
36
+ }
37
+ parseSingle(body, reqCtx) {
38
+ const product = this.newModel();
39
+ product.identifier = { key: body.id };
40
+ product.name = body.name[reqCtx.languageContext.locale] || body.id;
41
+ product.slug = body.slug?.[reqCtx.languageContext.locale] || body.id;
42
+ product.variants = [body.masterVariant, ...body.variants].map((variant) => this.parseVariant(variant, body, reqCtx));
43
+ return product;
44
+ }
45
+ parsePaginatedResult(body, reqCtx) {
46
+ const products = body.results.map((p) => this.parseSingle(p, reqCtx));
47
+ const facets = [];
48
+ for (const id in body.facets) {
49
+ const f = body.facets[id];
50
+ const facetId = FacetIdentifierSchema.parse({
51
+ key: id
52
+ });
53
+ const facet = this.parseFacet(facetId, f, reqCtx);
54
+ facets.push(facet);
55
+ }
56
+ const result = createPaginatedResponseSchema(this.schema).parse({
57
+ meta: {
58
+ cache: { hit: false, key: "unknown" },
59
+ placeholder: false
60
+ },
61
+ pageNumber: (Math.ceil(body.offset / body.limit) || 0) + 1,
62
+ pageSize: body.limit,
63
+ totalCount: body.total,
64
+ totalPages: Math.ceil((body.total || 0) / body.limit || 0) + 1,
65
+ items: products
66
+ });
67
+ result.facets = facets;
68
+ return result;
69
+ }
70
+ parseFacet(facetIdentifier, facetValue, reqCtx) {
71
+ const result = ProductSearchResultFacetSchema.parse({
72
+ identifier: facetIdentifier,
73
+ name: facetIdentifier.key,
74
+ values: []
75
+ });
76
+ if (facetValue.type === "terms") {
77
+ for (const ft of facetValue.terms) {
78
+ const facetValueIdentifier = FacetValueIdentifierSchema.parse({
79
+ facet: facetIdentifier,
80
+ key: ft.term
81
+ });
82
+ result.values.push(this.parseFacetValue(facetValueIdentifier, ft.term, ft.count, reqCtx));
83
+ }
84
+ }
85
+ return result;
86
+ }
87
+ parseFacetValue(facetValueIdentifier, label, count, reqCtx) {
88
+ return ProductSearchResultFacetValueSchema.parse({
89
+ identifier: facetValueIdentifier,
90
+ name: label,
91
+ count,
92
+ active: false
93
+ });
94
+ }
95
+ parseVariant(variant, product, reqCtx) {
96
+ const sourceImage = variant.images?.[0];
97
+ const img = ImageSchema.parse({
98
+ sourceUrl: sourceImage?.url || "",
99
+ height: sourceImage?.dimensions.h || void 0,
100
+ width: sourceImage?.dimensions.w || void 0,
101
+ altText: sourceImage?.label || product.name[reqCtx.languageContext.locale] || void 0
102
+ });
103
+ const mappedOptions = variant.attributes?.filter((x) => x.name === "Color").map(
104
+ (opt) => ProductVariantOptionSchema.parse(
105
+ {
106
+ identifier: ProductOptionIdentifierSchema.parse({
107
+ key: opt.name
108
+ }),
109
+ name: opt.value || ""
110
+ }
111
+ )
112
+ ) || [];
113
+ const mappedOption = mappedOptions?.[0];
114
+ return ProductSearchResultItemVariantSchema.parse({
115
+ variant: ProductVariantIdentifierSchema.parse({ sku: variant.sku || "" }),
116
+ image: img,
117
+ option: mappedOption
118
+ });
119
+ }
120
+ }
121
+ export {
122
+ CommercetoolsSearchProvider
123
+ };
@@ -1,5 +1,12 @@
1
1
  import {
2
- ProductProvider
2
+ ImageSchema,
3
+ ProductAttributeIdentifierSchema,
4
+ ProductAttributeSchema,
5
+ ProductAttributeValueIdentifierSchema,
6
+ ProductAttributeValueSchema,
7
+ ProductProvider,
8
+ ProductVariantIdentifierSchema,
9
+ ProductVariantSchema
3
10
  } from "@reactionary/core";
4
11
  import { CommercetoolsClient } from "../core/client.js";
5
12
  class CommercetoolsProductProvider extends ProductProvider {
@@ -40,13 +47,12 @@ class CommercetoolsProductProvider extends ProductProvider {
40
47
  staged: false,
41
48
  limit: 1,
42
49
  where: "variants(sku in (:skus)) OR (masterVariant(sku in (:skus))) ",
43
- "var.skus": [payload].map((p) => p.sku.key)
50
+ "var.skus": [payload].map((p) => p.variant.sku)
44
51
  }
45
52
  }).execute();
46
53
  return this.parseSingle(remote.body.results[0], reqCtx);
47
54
  }
48
- parseSingle(dataIn, reqCtx) {
49
- const data = dataIn;
55
+ parseSingle(data, reqCtx) {
50
56
  const base = this.newModel();
51
57
  base.identifier = { key: data.id };
52
58
  base.name = data.name[reqCtx.languageContext.locale];
@@ -54,26 +60,64 @@ class CommercetoolsProductProvider extends ProductProvider {
54
60
  if (data.description) {
55
61
  base.description = data.description[reqCtx.languageContext.locale];
56
62
  }
57
- if (data.masterVariant.images && data.masterVariant.images.length > 0) {
58
- base.image = data.masterVariant.images[0].url;
59
- }
60
- base.images = [];
61
- base.attributes = [];
62
- base.skus = [];
63
- const variants = [data.masterVariant, ...data.variants];
64
- for (const variant of variants) {
65
- if (variant.sku) {
66
- base.skus.push({
67
- identifier: { key: variant.sku }
68
- });
69
- }
70
- }
63
+ base.sharedAttributes = data.masterVariant.attributes?.map((x) => this.parseAttribute(x, reqCtx)) || [];
64
+ base.mainVariant = this.parseVariant(data.masterVariant, data, reqCtx);
71
65
  base.meta = {
72
66
  cache: { hit: false, key: this.generateCacheKeySingle(base.identifier, reqCtx) },
73
67
  placeholder: false
74
68
  };
75
69
  return this.assert(base);
76
70
  }
71
+ parseVariant(variant, product, reqCtx) {
72
+ const result = ProductVariantSchema.parse({
73
+ identifier: ProductVariantIdentifierSchema.parse({
74
+ sku: variant.sku
75
+ }),
76
+ images: [
77
+ ...(variant.images || []).map((img) => ImageSchema.parse({
78
+ sourceUrl: img.url,
79
+ altText: img.label || "",
80
+ width: img.dimensions?.w,
81
+ height: img.dimensions?.h
82
+ }))
83
+ ]
84
+ });
85
+ return result;
86
+ }
87
+ parseAttribute(attr, reqCtx) {
88
+ const result = ProductAttributeSchema.parse({
89
+ identifier: ProductAttributeIdentifierSchema.parse({
90
+ key: attr.name
91
+ }),
92
+ group: "",
93
+ name: attr.name,
94
+ values: [
95
+ this.parseAttributeValue(attr, reqCtx)
96
+ ]
97
+ });
98
+ return result;
99
+ }
100
+ parseAttributeValue(attr, reqCtx) {
101
+ let attrValue = "";
102
+ if (attr.value && Array.isArray(attr.value)) {
103
+ attrValue = attr.value[0];
104
+ }
105
+ if (attrValue && typeof attrValue === "object") {
106
+ if (reqCtx.languageContext.locale in attrValue) {
107
+ attrValue = attrValue[reqCtx.languageContext.locale];
108
+ } else {
109
+ attrValue = "-";
110
+ }
111
+ }
112
+ const attrVal = ProductAttributeValueSchema.parse({
113
+ identifier: ProductAttributeValueIdentifierSchema.parse({
114
+ key: attrValue
115
+ }),
116
+ value: String(attrValue),
117
+ label: String(attrValue)
118
+ });
119
+ return attrVal;
120
+ }
77
121
  }
78
122
  export {
79
123
  CommercetoolsProductProvider
@@ -1,7 +1,7 @@
1
1
  import { CapabilitiesSchema } from "@reactionary/core";
2
2
  const CommercetoolsCapabilitiesSchema = CapabilitiesSchema.pick({
3
3
  product: true,
4
- search: true,
4
+ productSearch: true,
5
5
  identity: true,
6
6
  cart: true,
7
7
  checkout: true,
@@ -1,12 +1,12 @@
1
- import type { Cache, ProductProvider, SearchProvider, IdentityProvider, CartProvider, InventoryProvider, PriceProvider, CategoryProvider, StoreProvider, CheckoutProvider, OrderProvider } from "@reactionary/core";
1
+ import type { Cache, ProductProvider, ProductSearchProvider, IdentityProvider, CartProvider, InventoryProvider, PriceProvider, CategoryProvider, StoreProvider, CheckoutProvider, OrderProvider } from "@reactionary/core";
2
2
  import type { CommercetoolsCapabilities } from "../schema/capabilities.schema.js";
3
3
  import type { CommercetoolsConfiguration } from "../schema/configuration.schema.js";
4
4
  type CommercetoolsClient<T extends CommercetoolsCapabilities> = (T['cart'] extends true ? {
5
5
  cart: CartProvider;
6
6
  } : object) & (T['product'] extends true ? {
7
7
  product: ProductProvider;
8
- } : object) & (T['search'] extends true ? {
9
- search: SearchProvider;
8
+ } : object) & (T['productSearch'] extends true ? {
9
+ productSearch: ProductSearchProvider;
10
10
  } : object) & (T['identity'] extends true ? {
11
11
  identity: IdentityProvider;
12
12
  } : object) & (T['category'] extends true ? {
package/src/index.d.ts CHANGED
@@ -5,6 +5,6 @@ export * from './providers/identity.provider.js';
5
5
  export * from './providers/inventory.provider.js';
6
6
  export * from './providers/price.provider.js';
7
7
  export * from './providers/product.provider.js';
8
- export * from './providers/search.provider.js';
8
+ export * from './providers/product-search.provider.js';
9
9
  export * from './schema/capabilities.schema.js';
10
10
  export * from './schema/configuration.schema.js';
@@ -5,7 +5,7 @@ export * from './inventory.provider.js';
5
5
  export * from './price.provider.js';
6
6
  export * from './product.provider.js';
7
7
  export * from './profile.provider.js';
8
- export * from './search.provider.js';
8
+ export * from './product-search.provider.js';
9
9
  export * from './store.provider.js';
10
10
  export * from './order.provider.js';
11
11
  export * from './checkout.provider.js';
@@ -0,0 +1,31 @@
1
+ import { ProductSearchProvider } from '@reactionary/core';
2
+ import type { Cache, ProductSearchQueryByTerm, RequestContext, ProductSearchResultItem, ProductSearchResult, ProductSearchResultItemVariant, FacetIdentifier, ProductSearchResultFacet, FacetValueIdentifier, ProductSearchResultFacetValue } from '@reactionary/core';
3
+ import type z from 'zod';
4
+ import type { CommercetoolsConfiguration } from '../schema/configuration.schema.js';
5
+ import type { ProductVariant as CTProductVariant, FacetResult, ProductProjection, ProductProjectionPagedSearchResponse } from '@commercetools/platform-sdk';
6
+ export declare class CommercetoolsSearchProvider<T extends ProductSearchResultItem = ProductSearchResultItem> extends ProductSearchProvider<T> {
7
+ protected config: CommercetoolsConfiguration;
8
+ constructor(config: CommercetoolsConfiguration, schema: z.ZodType<T>, cache: Cache);
9
+ protected getClient(reqCtx: RequestContext): Promise<import("@commercetools/platform-sdk").ByProjectKeyProductProjectionsRequestBuilder>;
10
+ queryByTerm(payload: ProductSearchQueryByTerm, reqCtx: RequestContext): Promise<ProductSearchResult>;
11
+ protected parseSingle(body: ProductProjection, reqCtx: RequestContext): T;
12
+ protected parsePaginatedResult(body: ProductProjectionPagedSearchResponse, reqCtx: RequestContext): {
13
+ meta: {
14
+ [x: string]: unknown;
15
+ cache: {
16
+ [x: string]: unknown;
17
+ hit: boolean;
18
+ key: string;
19
+ };
20
+ placeholder: boolean;
21
+ };
22
+ pageNumber: number;
23
+ pageSize: number;
24
+ totalCount: number;
25
+ totalPages: number;
26
+ items: T[];
27
+ };
28
+ protected parseFacet(facetIdentifier: FacetIdentifier, facetValue: FacetResult, reqCtx: RequestContext): ProductSearchResultFacet;
29
+ protected parseFacetValue(facetValueIdentifier: FacetValueIdentifier, label: string, count: number, reqCtx: RequestContext): ProductSearchResultFacetValue;
30
+ protected parseVariant(variant: CTProductVariant, product: ProductProjection, reqCtx: RequestContext): ProductSearchResultItemVariant;
31
+ }
@@ -1,7 +1,8 @@
1
1
  import { ProductProvider } from '@reactionary/core';
2
2
  import type { z } from 'zod';
3
3
  import type { CommercetoolsConfiguration } from '../schema/configuration.schema.js';
4
- import type { Product, ProductQueryById, ProductQueryBySKU, ProductQueryBySlug, RequestContext } from '@reactionary/core';
4
+ import type { ProductProjection, ProductVariant as CTProductVariant, Attribute as CTAttribute } from '@commercetools/platform-sdk';
5
+ import type { Product, ProductVariant, ProductQueryById, ProductQueryBySKU, ProductQueryBySlug, RequestContext, ProductAttribute, ProductAttributeValue } from '@reactionary/core';
5
6
  import type { Cache } from '@reactionary/core';
6
7
  export declare class CommercetoolsProductProvider<T extends Product = Product> extends ProductProvider<T> {
7
8
  protected config: CommercetoolsConfiguration;
@@ -10,5 +11,8 @@ export declare class CommercetoolsProductProvider<T extends Product = Product> e
10
11
  getById(payload: ProductQueryById, reqCtx: RequestContext): Promise<T>;
11
12
  getBySlug(payload: ProductQueryBySlug, reqCtx: RequestContext): Promise<T | null>;
12
13
  getBySKU(payload: ProductQueryBySKU, reqCtx: RequestContext): Promise<T>;
13
- protected parseSingle(dataIn: unknown, reqCtx: RequestContext): T;
14
+ protected parseSingle(data: ProductProjection, reqCtx: RequestContext): T;
15
+ protected parseVariant(variant: CTProductVariant, product: ProductProjection, reqCtx: RequestContext): ProductVariant;
16
+ protected parseAttribute(attr: CTAttribute, reqCtx: RequestContext): ProductAttribute;
17
+ protected parseAttributeValue(attr: CTAttribute, reqCtx: RequestContext): ProductAttributeValue;
14
18
  }
@@ -3,12 +3,12 @@ export declare const CommercetoolsCapabilitiesSchema: z.ZodObject<{
3
3
  price: z.ZodOptional<z.ZodBoolean>;
4
4
  product: z.ZodOptional<z.ZodBoolean>;
5
5
  identity: z.ZodOptional<z.ZodBoolean>;
6
- search: z.ZodOptional<z.ZodBoolean>;
7
6
  cart: z.ZodOptional<z.ZodBoolean>;
8
7
  inventory: z.ZodOptional<z.ZodBoolean>;
9
8
  category: z.ZodOptional<z.ZodBoolean>;
10
9
  checkout: z.ZodOptional<z.ZodBoolean>;
11
10
  order: z.ZodOptional<z.ZodBoolean>;
12
11
  store: z.ZodOptional<z.ZodBoolean>;
12
+ productSearch: z.ZodOptional<z.ZodBoolean>;
13
13
  }, z.core.$loose>;
14
14
  export type CommercetoolsCapabilities = z.infer<typeof CommercetoolsCapabilitiesSchema>;
@@ -1,48 +0,0 @@
1
- import { SearchProvider } from "@reactionary/core";
2
- import { CommercetoolsClient } from "../core/client.js";
3
- class CommercetoolsSearchProvider extends SearchProvider {
4
- constructor(config, schema, cache) {
5
- super(schema, cache);
6
- this.config = config;
7
- }
8
- async getClient(reqCtx) {
9
- const client = await new CommercetoolsClient(this.config).getClient(reqCtx);
10
- return client.withProjectKey({ projectKey: this.config.projectKey }).productProjections();
11
- }
12
- async queryByTerm(payload, reqCtx) {
13
- const client = await this.getClient(reqCtx);
14
- const remote = await client.search().get({
15
- queryArgs: {
16
- limit: payload.search.pageSize,
17
- offset: (payload.search.page - 1) * payload.search.pageSize,
18
- [`text.${reqCtx.languageContext.locale}`]: payload.search.term
19
- }
20
- }).execute();
21
- return this.parseSearchResult(remote, payload, reqCtx);
22
- }
23
- parseSearchResult(remote, payload, reqCtx) {
24
- const result = this.newModel();
25
- const remoteData = remote;
26
- result.identifier = payload.search;
27
- for (const p of remoteData.body.results) {
28
- const product = {
29
- identifier: { key: p.id },
30
- name: p.name[reqCtx.languageContext.locale] || p.id,
31
- slug: p.slug?.[reqCtx.languageContext.locale] || p.id,
32
- image: p.masterVariant.images?.[0]?.url || "https://placehold.co/400"
33
- };
34
- result.products.push(product);
35
- }
36
- result.pages = Math.ceil(
37
- (remoteData.body.total || 0) / payload.search.pageSize
38
- );
39
- result.meta = {
40
- cache: { hit: false, key: payload.search.term },
41
- placeholder: false
42
- };
43
- return this.assert(result);
44
- }
45
- }
46
- export {
47
- CommercetoolsSearchProvider
48
- };
@@ -1,11 +0,0 @@
1
- import { SearchProvider } from '@reactionary/core';
2
- import type { SearchResult, Cache, SearchQueryByTerm, RequestContext } from '@reactionary/core';
3
- import type z from 'zod';
4
- import type { CommercetoolsConfiguration } from '../schema/configuration.schema.js';
5
- export declare class CommercetoolsSearchProvider<T extends SearchResult = SearchResult> extends SearchProvider<T> {
6
- protected config: CommercetoolsConfiguration;
7
- constructor(config: CommercetoolsConfiguration, schema: z.ZodType<T>, cache: Cache);
8
- protected getClient(reqCtx: RequestContext): Promise<import("@commercetools/platform-sdk").ByProjectKeyProductProjectionsRequestBuilder>;
9
- queryByTerm(payload: SearchQueryByTerm, reqCtx: RequestContext): Promise<T>;
10
- protected parseSearchResult(remote: unknown, payload: SearchQueryByTerm, reqCtx: RequestContext): T;
11
- }