@reactionary/core 0.3.2 → 0.3.4
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/client/client-builder.js +6 -0
- package/package.json +1 -1
- package/providers/index.js +2 -0
- package/providers/product-associations.provider.js +9 -0
- package/providers/product-recommendations.provider.js +129 -0
- package/schemas/capabilities.schema.js +2 -0
- package/schemas/models/identifiers.model.js +5 -0
- package/schemas/models/index.js +1 -0
- package/schemas/models/product-recommendations.model.js +9 -0
- package/schemas/queries/index.js +2 -0
- package/schemas/queries/product-associations.query.js +19 -0
- package/schemas/queries/product-recommendations.query.js +59 -0
- package/src/client/client.d.ts +4 -0
- package/src/providers/index.d.ts +2 -0
- package/src/providers/product-associations.provider.d.ts +35 -0
- package/src/providers/product-recommendations.provider.d.ts +32 -0
- package/src/schemas/capabilities.schema.d.ts +2 -0
- package/src/schemas/models/identifiers.model.d.ts +6 -1
- package/src/schemas/models/index.d.ts +1 -0
- package/src/schemas/models/product-recommendations.model.d.ts +11 -0
- package/src/schemas/queries/index.d.ts +2 -0
- package/src/schemas/queries/product-associations.query.d.ts +20 -0
- package/src/schemas/queries/product-recommendations.query.d.ts +127 -0
package/client/client-builder.js
CHANGED
|
@@ -3,6 +3,7 @@ import { MulticastAnalyticsProvider } from "../providers/analytics.provider.js";
|
|
|
3
3
|
import {
|
|
4
4
|
RequestContextSchema
|
|
5
5
|
} from "../schemas/session.schema.js";
|
|
6
|
+
import { MulticastProductRecommendationsProvider } from "../providers/product-recommendations.provider.js";
|
|
6
7
|
class ClientBuilder {
|
|
7
8
|
constructor(context) {
|
|
8
9
|
this.factories = [];
|
|
@@ -30,6 +31,7 @@ class ClientBuilder {
|
|
|
30
31
|
throw new Error("Invalid context: " + validatedContext.error);
|
|
31
32
|
}
|
|
32
33
|
const mergedAnalytics = [];
|
|
34
|
+
const mergedProductRecommendationsProviders = [];
|
|
33
35
|
for (const factory of this.factories) {
|
|
34
36
|
const provider = factory(sharedCache, this.context);
|
|
35
37
|
client = {
|
|
@@ -39,10 +41,14 @@ class ClientBuilder {
|
|
|
39
41
|
if (provider.analytics) {
|
|
40
42
|
mergedAnalytics.push(provider.analytics);
|
|
41
43
|
}
|
|
44
|
+
if (provider.productRecommendations) {
|
|
45
|
+
mergedProductRecommendationsProviders.push(provider.productRecommendations);
|
|
46
|
+
}
|
|
42
47
|
}
|
|
43
48
|
const completeClient = {
|
|
44
49
|
...client,
|
|
45
50
|
analytics: new MulticastAnalyticsProvider(sharedCache, this.context, mergedAnalytics),
|
|
51
|
+
productRecommendations: new MulticastProductRecommendationsProvider(sharedCache, this.context, mergedProductRecommendationsProviders),
|
|
46
52
|
cache: sharedCache
|
|
47
53
|
};
|
|
48
54
|
return completeClient;
|
package/package.json
CHANGED
package/providers/index.js
CHANGED
|
@@ -9,6 +9,8 @@ export * from "./price.provider.js";
|
|
|
9
9
|
export * from "./product.provider.js";
|
|
10
10
|
export * from "./profile.provider.js";
|
|
11
11
|
export * from "./product-search.provider.js";
|
|
12
|
+
export * from "./product-recommendations.provider.js";
|
|
13
|
+
export * from "./product-associations.provider.js";
|
|
12
14
|
export * from "./store.provider.js";
|
|
13
15
|
export * from "./order.provider.js";
|
|
14
16
|
export * from "./order-search.provider.js";
|
|
@@ -0,0 +1,129 @@
|
|
|
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 { Reactionary } from "../decorators/reactionary.decorator.js";
|
|
13
|
+
import { success } from "../schemas/index.js";
|
|
14
|
+
import { ProductRecommendationsQuerySchema } from "../schemas/queries/product-recommendations.query.js";
|
|
15
|
+
import { BaseProvider } from "./base.provider.js";
|
|
16
|
+
class ProductRecommendationsProvider extends BaseProvider {
|
|
17
|
+
/**
|
|
18
|
+
* returns a list of recommended products, based on the selected algorithm and the provided query parameters. The recommendations should be relevant to the product specified in the query, and can be personalized based on the customer segments or contexts provided. The provider should return a list of product variant identifiers that are recommended for the given product, which can then be used to fetch the full product details from the product provider if needed.
|
|
19
|
+
* *
|
|
20
|
+
* Usecase:
|
|
21
|
+
* - PDP - "Customers who viewed this product also viewed"
|
|
22
|
+
* - Cart - "You might also like"
|
|
23
|
+
* - Post-purchase - "Customers who bought this product also bought"
|
|
24
|
+
* - Article page: "Products related to the product mentioned in this article"
|
|
25
|
+
* @param query
|
|
26
|
+
*/
|
|
27
|
+
async getRecommendations(query) {
|
|
28
|
+
if (query.algorithm === "frequentlyBoughtTogether") {
|
|
29
|
+
return success(await this.getFrequentlyBoughtTogetherRecommendations(query));
|
|
30
|
+
}
|
|
31
|
+
if (query.algorithm === "similar") {
|
|
32
|
+
return success(await this.getSimilarProductsRecommendations(query));
|
|
33
|
+
}
|
|
34
|
+
if (query.algorithm === "related") {
|
|
35
|
+
return success(await this.getRelatedProductsRecommendations(query));
|
|
36
|
+
}
|
|
37
|
+
if (query.algorithm === "trendingInCategory") {
|
|
38
|
+
return success(await this.getTrendingInCategoryRecommendations(query));
|
|
39
|
+
}
|
|
40
|
+
if (query.algorithm === "popular") {
|
|
41
|
+
return success(await this.getPopularProductsRecommendations(query));
|
|
42
|
+
}
|
|
43
|
+
if (query.algorithm === "topPicks") {
|
|
44
|
+
return success(await this.getTopPicksProductsRecommendations(query));
|
|
45
|
+
}
|
|
46
|
+
if (query.algorithm === "alsoViewed") {
|
|
47
|
+
return success(await this.getAlsoViewedProductsRecommendations(query));
|
|
48
|
+
}
|
|
49
|
+
return success([]);
|
|
50
|
+
}
|
|
51
|
+
async getCollection(query) {
|
|
52
|
+
return success([]);
|
|
53
|
+
}
|
|
54
|
+
async getFrequentlyBoughtTogetherRecommendations(query) {
|
|
55
|
+
return [];
|
|
56
|
+
}
|
|
57
|
+
async getSimilarProductsRecommendations(query) {
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
async getTrendingInCategoryRecommendations(query) {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
async getRelatedProductsRecommendations(query) {
|
|
64
|
+
return [];
|
|
65
|
+
}
|
|
66
|
+
async getPopularProductsRecommendations(query) {
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
async getTopPicksProductsRecommendations(query) {
|
|
70
|
+
return [];
|
|
71
|
+
}
|
|
72
|
+
async getAlsoViewedProductsRecommendations(query) {
|
|
73
|
+
return [];
|
|
74
|
+
}
|
|
75
|
+
getResourceName() {
|
|
76
|
+
return "product-recommendations";
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
class MulticastProductRecommendationsProvider extends ProductRecommendationsProvider {
|
|
80
|
+
constructor(cache, requestContext, providers) {
|
|
81
|
+
super(cache, requestContext);
|
|
82
|
+
this.providers = providers;
|
|
83
|
+
}
|
|
84
|
+
async getRecommendations(query) {
|
|
85
|
+
const output = [];
|
|
86
|
+
for (const provider of this.providers) {
|
|
87
|
+
const providerOutput = await provider.getRecommendations(query);
|
|
88
|
+
if (providerOutput.success) {
|
|
89
|
+
output.push(...providerOutput.value);
|
|
90
|
+
} else {
|
|
91
|
+
console.error(`Error from provider ${provider.constructor.name}:`, providerOutput.error);
|
|
92
|
+
return providerOutput;
|
|
93
|
+
}
|
|
94
|
+
if (output.length >= query.numberOfRecommendations) {
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return success(output.slice(0, query.numberOfRecommendations));
|
|
99
|
+
}
|
|
100
|
+
async getCollection(query) {
|
|
101
|
+
const output = [];
|
|
102
|
+
for (const provider of this.providers) {
|
|
103
|
+
const providerOutput = await provider.getCollection(query);
|
|
104
|
+
if (providerOutput.success) {
|
|
105
|
+
output.push(...providerOutput.value);
|
|
106
|
+
} else {
|
|
107
|
+
if (providerOutput.error.type === "NotFound") {
|
|
108
|
+
continue;
|
|
109
|
+
} else {
|
|
110
|
+
console.error(`Error from provider ${provider.constructor.name}:`, providerOutput.error);
|
|
111
|
+
return providerOutput;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (output.length >= query.numberOfRecommendations) {
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return success(output.slice(0, query.numberOfRecommendations));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
__decorateClass([
|
|
122
|
+
Reactionary({
|
|
123
|
+
inputSchema: ProductRecommendationsQuerySchema
|
|
124
|
+
})
|
|
125
|
+
], MulticastProductRecommendationsProvider.prototype, "getRecommendations", 1);
|
|
126
|
+
export {
|
|
127
|
+
MulticastProductRecommendationsProvider,
|
|
128
|
+
ProductRecommendationsProvider
|
|
129
|
+
};
|
|
@@ -2,6 +2,8 @@ import { z } from "zod";
|
|
|
2
2
|
const CapabilitiesSchema = z.looseObject({
|
|
3
3
|
product: z.boolean(),
|
|
4
4
|
productSearch: z.boolean(),
|
|
5
|
+
productAssociations: z.boolean(),
|
|
6
|
+
productRecommendations: z.boolean(),
|
|
5
7
|
analytics: z.boolean(),
|
|
6
8
|
identity: z.boolean(),
|
|
7
9
|
cart: z.boolean(),
|
|
@@ -85,6 +85,10 @@ const PaymentInstructionIdentifierSchema = z.looseObject({
|
|
|
85
85
|
const PickupPointIdentifierSchema = z.looseObject({
|
|
86
86
|
key: z.string()
|
|
87
87
|
});
|
|
88
|
+
const ProductRecommendationIdentifierSchema = z.looseObject({
|
|
89
|
+
key: z.string(),
|
|
90
|
+
algorithm: z.string()
|
|
91
|
+
});
|
|
88
92
|
const ProductSearchIdentifierSchema = z.looseObject({
|
|
89
93
|
term: z.string().describe("The search term used to find products."),
|
|
90
94
|
facets: z.array(FacetValueIdentifierSchema).describe("The facets applied to filter the search results."),
|
|
@@ -128,6 +132,7 @@ export {
|
|
|
128
132
|
ProductIdentifierSchema,
|
|
129
133
|
ProductOptionIdentifierSchema,
|
|
130
134
|
ProductOptionValueIdentifierSchema,
|
|
135
|
+
ProductRecommendationIdentifierSchema,
|
|
131
136
|
ProductSearchIdentifierSchema,
|
|
132
137
|
ProductVariantIdentifierSchema,
|
|
133
138
|
ShippingMethodIdentifierSchema,
|
package/schemas/models/index.js
CHANGED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import z from "zod";
|
|
2
|
+
import { ProductIdentifierSchema, ProductRecommendationIdentifierSchema, ProductVariantIdentifierSchema } from "./identifiers.model.js";
|
|
3
|
+
const ProductRecommendationSchema = z.looseObject({
|
|
4
|
+
recommendationIdentifier: ProductRecommendationIdentifierSchema.describe("The identifier for the product recommendation, which includes a key and an algorithm and any other vendor specific/instance specific data "),
|
|
5
|
+
product: ProductIdentifierSchema.describe("The identifier for the recommended product.")
|
|
6
|
+
});
|
|
7
|
+
export {
|
|
8
|
+
ProductRecommendationSchema
|
|
9
|
+
};
|
package/schemas/queries/index.js
CHANGED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import z from "zod";
|
|
2
|
+
import { BaseQuerySchema } from "./base.query.js";
|
|
3
|
+
import { ProductIdentifierSchema, ProductVariantIdentifierSchema } from "../models/identifiers.model.js";
|
|
4
|
+
import { CartItemSchema } from "../models/cart.model.js";
|
|
5
|
+
const ProductAssociationsGetAccessoriesQuerySchema = BaseQuerySchema.extend({
|
|
6
|
+
forProductVariant: ProductVariantIdentifierSchema.describe("The product variant identifier for which to get accessory recommendations. The provider should return recommendations that are relevant to this product, e.g., products that are frequently bought together, products that are similar in style or category, or products that are popular among users with similar preferences."),
|
|
7
|
+
numberOfAccessories: z.number().min(1).max(12).describe("The number of accessory recommendations requested. The provider may return fewer than this number, but should not return more.")
|
|
8
|
+
});
|
|
9
|
+
const ProductAssociationsGetSparepartsQuerySchema = BaseQuerySchema.extend({
|
|
10
|
+
forProductVariant: ProductVariantIdentifierSchema.describe("The product variant identifier for which to get similar item recommendations. The provider should return recommendations that are relevant to this product, e.g., products that are frequently bought together, products that are similar in style or category, or products that are popular among users with similar preferences.")
|
|
11
|
+
});
|
|
12
|
+
const ProductAssociationsGetReplacementsQuerySchema = BaseQuerySchema.extend({
|
|
13
|
+
forProductVariant: ProductVariantIdentifierSchema.describe("The product variant identifier for which to get replacement recommendations. The provider should return recommendations that are relevant to this product, e.g., products that are frequently bought together, products that are similar in style or category, or products that are popular among users with similar preferences.")
|
|
14
|
+
});
|
|
15
|
+
export {
|
|
16
|
+
ProductAssociationsGetAccessoriesQuerySchema,
|
|
17
|
+
ProductAssociationsGetReplacementsQuerySchema,
|
|
18
|
+
ProductAssociationsGetSparepartsQuerySchema
|
|
19
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import z from "zod";
|
|
2
|
+
import { CategoryIdentifierSchema, ProductIdentifierSchema } from "../models/identifiers.model.js";
|
|
3
|
+
import { BaseQuerySchema } from "./base.query.js";
|
|
4
|
+
const ProductRecommendationBaseQuerySchema = BaseQuerySchema.extend({
|
|
5
|
+
numberOfRecommendations: z.number().min(1).max(12).describe("The number of recommendations requested. The provider may return fewer than this number, but should not return more."),
|
|
6
|
+
labels: z.array(z.string()).optional().describe("The customer segments, quirks, chirps or other labels to which the recommendations can optimize themselves to be relevant. This can be used by the provider to personalize the recommendations based on the preferences and behaviors of users in these segments.")
|
|
7
|
+
});
|
|
8
|
+
const ProductRecommendationsByCollectionQuerySchema = ProductRecommendationBaseQuerySchema.extend({
|
|
9
|
+
collectionName: z.string().describe("The name of the collection for which to get product recommendations. This is to access either manually curated lists, or interface marketing rules engines that define zones by name"),
|
|
10
|
+
sourceProduct: z.array(ProductIdentifierSchema).optional().describe("The products on screen or in the context you are asking for the recommendations. Could be all the variants from the current cart (resolved into their products), or just the variant of the PDP, or the 4 first products of a category."),
|
|
11
|
+
sourceCategory: CategoryIdentifierSchema.optional().describe("The category identifier to use as a seed for the recommendations. The provider should return recommendations that are relevant to this category, e.g., products that are frequently bought together, products that are similar in style or category, or products that are popular among users with similar preferences. This is optional, as the collection may already be curated to be relevant to a specific product or category, but it can be used by the provider to further personalize the recommendations based on the preferences and behaviors of users who have interacted with this category.")
|
|
12
|
+
});
|
|
13
|
+
const ProductRecommendationProductBasedBaseQuerySchema = ProductRecommendationBaseQuerySchema.extend({
|
|
14
|
+
sourceProduct: ProductIdentifierSchema.describe("The product identifiers for which to get recommendations. The provider should return recommendations that are relevant to these products, e.g., products that are frequently bought together, products that are similar in style or category, or products that are popular among users with similar preferences.")
|
|
15
|
+
});
|
|
16
|
+
const ProductRecommendationAlgorithmFrequentlyBoughtTogetherQuerySchema = ProductRecommendationProductBasedBaseQuerySchema.extend({
|
|
17
|
+
algorithm: z.literal("frequentlyBoughtTogether").describe("The provider should return recommendations based on products that are frequently bought together with the source products. The provider should leverage the Request Context to personalize the recommendations as much as possible, taking into account factors such as the user's browsing history, purchase history, and demographic information.")
|
|
18
|
+
});
|
|
19
|
+
const ProductRecommendationAlgorithmSimilarProductsQuerySchema = ProductRecommendationProductBasedBaseQuerySchema.extend({
|
|
20
|
+
algorithm: z.literal("similar").describe("The provider should return recommendations based on products that are similar to the source products either visually or data wise")
|
|
21
|
+
});
|
|
22
|
+
const ProductRecommendationAlgorithmRelatedProductsQuerySchema = ProductRecommendationProductBasedBaseQuerySchema.extend({
|
|
23
|
+
algorithm: z.literal("related").describe("The provider should return recommendations based on products that are related to the source products. ")
|
|
24
|
+
});
|
|
25
|
+
const ProductRecommendationAlgorithmTrendingInCategoryQuerySchema = ProductRecommendationBaseQuerySchema.extend({
|
|
26
|
+
algorithm: z.literal("trendingInCategory").describe("The provider should return recommendations based on products that are trending in the specified category. The provider should leverage the Request Context to personalize the recommendations as much as possible, taking into account factors such as the user's browsing history, purchase history, and demographic information."),
|
|
27
|
+
sourceCategory: CategoryIdentifierSchema.describe("The category identifier for which to get trending product recommendations. The provider should return recommendations that are relevant to this category, e.g., products that are frequently bought together, products that are similar in style or category, or products that are popular among users with similar preferences.")
|
|
28
|
+
});
|
|
29
|
+
const ProductRecommendationAlgorithmPopuplarProductsQuerySchema = ProductRecommendationBaseQuerySchema.extend({
|
|
30
|
+
algorithm: z.literal("popular").describe("The provider should return recommendations based on products that are popular among users. The provider should leverage the Request Context to personalize the recommendations as much as possible, taking into account factors such as the user's browsing history, purchase history, and demographic information.")
|
|
31
|
+
});
|
|
32
|
+
const ProductRecommendationAlgorithmTopPicksProductsQuerySchema = ProductRecommendationBaseQuerySchema.extend({
|
|
33
|
+
algorithm: z.literal("topPicks").describe("The provider should return recommendations based on products that are top picks among users. The provider should leverage the Request Context to personalize the recommendations as much as possible, taking into account factors such as the user's browsing history, purchase history, and demographic information.")
|
|
34
|
+
});
|
|
35
|
+
const ProductRecommendationAlgorithmAlsoViewedProductsQuerySchema = ProductRecommendationProductBasedBaseQuerySchema.extend({
|
|
36
|
+
algorithm: z.literal("alsoViewed").describe("The provider should return recommendations based on products that are also viewed by users. The provider should leverage the Request Context to personalize the recommendations as much as possible, taking into account factors such as the user's browsing history, purchase history, and demographic information.")
|
|
37
|
+
});
|
|
38
|
+
const ProductRecommendationsQuerySchema = z.discriminatedUnion("algorithm", [
|
|
39
|
+
ProductRecommendationAlgorithmFrequentlyBoughtTogetherQuerySchema,
|
|
40
|
+
ProductRecommendationAlgorithmTrendingInCategoryQuerySchema,
|
|
41
|
+
ProductRecommendationAlgorithmSimilarProductsQuerySchema,
|
|
42
|
+
ProductRecommendationAlgorithmRelatedProductsQuerySchema,
|
|
43
|
+
ProductRecommendationAlgorithmPopuplarProductsQuerySchema,
|
|
44
|
+
ProductRecommendationAlgorithmTopPicksProductsQuerySchema,
|
|
45
|
+
ProductRecommendationAlgorithmAlsoViewedProductsQuerySchema
|
|
46
|
+
]);
|
|
47
|
+
export {
|
|
48
|
+
ProductRecommendationAlgorithmAlsoViewedProductsQuerySchema,
|
|
49
|
+
ProductRecommendationAlgorithmFrequentlyBoughtTogetherQuerySchema,
|
|
50
|
+
ProductRecommendationAlgorithmPopuplarProductsQuerySchema,
|
|
51
|
+
ProductRecommendationAlgorithmRelatedProductsQuerySchema,
|
|
52
|
+
ProductRecommendationAlgorithmSimilarProductsQuerySchema,
|
|
53
|
+
ProductRecommendationAlgorithmTopPicksProductsQuerySchema,
|
|
54
|
+
ProductRecommendationAlgorithmTrendingInCategoryQuerySchema,
|
|
55
|
+
ProductRecommendationBaseQuerySchema,
|
|
56
|
+
ProductRecommendationProductBasedBaseQuerySchema,
|
|
57
|
+
ProductRecommendationsByCollectionQuerySchema,
|
|
58
|
+
ProductRecommendationsQuerySchema
|
|
59
|
+
};
|
package/src/client/client.d.ts
CHANGED
|
@@ -8,9 +8,13 @@ import type { Cache } from "../cache/cache.interface.js";
|
|
|
8
8
|
import type { CategoryProvider } from "../providers/category.provider.js";
|
|
9
9
|
import type { AnalyticsProvider, CheckoutProvider, OrderProvider, ProfileProvider, StoreProvider } from "../providers/index.js";
|
|
10
10
|
import type { OrderSearchProvider } from "../providers/order-search.provider.js";
|
|
11
|
+
import type { ProductRecommendationsProvider } from "../providers/product-recommendations.provider.js";
|
|
12
|
+
import type { ProductAssociationsProvider } from "../providers/product-associations.provider.js";
|
|
11
13
|
export interface Client {
|
|
12
14
|
product: ProductProvider;
|
|
13
15
|
productSearch: ProductSearchProvider;
|
|
16
|
+
productRecommendations: ProductRecommendationsProvider;
|
|
17
|
+
productAssociations: ProductAssociationsProvider;
|
|
14
18
|
identity: IdentityProvider;
|
|
15
19
|
cache: Cache;
|
|
16
20
|
cart: CartProvider;
|
package/src/providers/index.d.ts
CHANGED
|
@@ -9,6 +9,8 @@ export * from './price.provider.js';
|
|
|
9
9
|
export * from './product.provider.js';
|
|
10
10
|
export * from './profile.provider.js';
|
|
11
11
|
export * from './product-search.provider.js';
|
|
12
|
+
export * from './product-recommendations.provider.js';
|
|
13
|
+
export * from './product-associations.provider.js';
|
|
12
14
|
export * from './store.provider.js';
|
|
13
15
|
export * from './order.provider.js';
|
|
14
16
|
export * from './order-search.provider.js';
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ProductVariantIdentifier } from "../schemas/index.js";
|
|
2
|
+
import type { ProductAssociationsGetAccessoriesQuery, ProductAssociationsGetSparepartsQuery, ProductAssociationsGetReplacementsQuery } from "../schemas/queries/product-associations.query.js";
|
|
3
|
+
import { BaseProvider } from "./base.provider.js";
|
|
4
|
+
/**
|
|
5
|
+
* The product association provider is responsible for providing evidence based associations between products, such as
|
|
6
|
+
* accessories, spareparts, and replacements. These associations are typically used to provide recommendations to customers on the product detail page, but can also be used in other contexts such as the cart or post-purchase, but
|
|
7
|
+
* do not carry any personalization concept to them.
|
|
8
|
+
*/
|
|
9
|
+
export declare abstract class ProductAssociationsProvider extends BaseProvider {
|
|
10
|
+
/**
|
|
11
|
+
* Returns a list of product identifiers which are accessories to the given product.
|
|
12
|
+
* Accessories in are products in their own right, but are commonly purchased alongside or recommended as complementary to the main product. Examples of accessories include:
|
|
13
|
+
* - A phone case for a smartphone
|
|
14
|
+
* - A camera bag for a camera
|
|
15
|
+
*
|
|
16
|
+
*
|
|
17
|
+
* Usecase:
|
|
18
|
+
* - PDP: Accessories for this product
|
|
19
|
+
*/
|
|
20
|
+
abstract getAccessories(query: ProductAssociationsGetAccessoriesQuery): Promise<ProductVariantIdentifier[]>;
|
|
21
|
+
/**
|
|
22
|
+
* Returns a list of product identifiers which are spareparts to the given product.
|
|
23
|
+
* Spareparts are products which are necessary for the use of the main product, but are not typically purchased alongside it. Examples of spareparts include:
|
|
24
|
+
*
|
|
25
|
+
* Usecase:
|
|
26
|
+
* - PDP: Accessories for this product
|
|
27
|
+
*/
|
|
28
|
+
abstract getSpareparts(query: ProductAssociationsGetSparepartsQuery): Promise<ProductVariantIdentifier[]>;
|
|
29
|
+
/**
|
|
30
|
+
* This product is replaced by these equivalent or newer products
|
|
31
|
+
* @param query
|
|
32
|
+
*/
|
|
33
|
+
abstract getReplacements(query: ProductAssociationsGetReplacementsQuery): Promise<ProductVariantIdentifier[]>;
|
|
34
|
+
getResourceName(): string;
|
|
35
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Cache } from '../cache/cache.interface.js';
|
|
2
|
+
import { type ProductRecommendation, type ProductRecommendationsByCollectionQuery, type RequestContext, type Result } from "../schemas/index.js";
|
|
3
|
+
import { type ProductRecommendationAlgorithmAlsoViewedProductsQuery, type ProductRecommendationAlgorithmFrequentlyBoughtTogetherQuery, type ProductRecommendationAlgorithmPopuplarProductsQuery, type ProductRecommendationAlgorithmRelatedProductsQuery, type ProductRecommendationAlgorithmSimilarProductsQuery, type ProductRecommendationAlgorithmTopPicksProductsQuery, type ProductRecommendationAlgorithmTrendingInCategoryQuery, type ProductRecommendationsQuery } from "../schemas/queries/product-recommendations.query.js";
|
|
4
|
+
import { BaseProvider } from "./base.provider.js";
|
|
5
|
+
export declare abstract class ProductRecommendationsProvider extends BaseProvider {
|
|
6
|
+
/**
|
|
7
|
+
* returns a list of recommended products, based on the selected algorithm and the provided query parameters. The recommendations should be relevant to the product specified in the query, and can be personalized based on the customer segments or contexts provided. The provider should return a list of product variant identifiers that are recommended for the given product, which can then be used to fetch the full product details from the product provider if needed.
|
|
8
|
+
* *
|
|
9
|
+
* Usecase:
|
|
10
|
+
* - PDP - "Customers who viewed this product also viewed"
|
|
11
|
+
* - Cart - "You might also like"
|
|
12
|
+
* - Post-purchase - "Customers who bought this product also bought"
|
|
13
|
+
* - Article page: "Products related to the product mentioned in this article"
|
|
14
|
+
* @param query
|
|
15
|
+
*/
|
|
16
|
+
getRecommendations(query: ProductRecommendationsQuery): Promise<Result<ProductRecommendation[]>>;
|
|
17
|
+
getCollection(query: ProductRecommendationsByCollectionQuery): Promise<Result<ProductRecommendation[]>>;
|
|
18
|
+
protected getFrequentlyBoughtTogetherRecommendations(query: ProductRecommendationAlgorithmFrequentlyBoughtTogetherQuery): Promise<ProductRecommendation[]>;
|
|
19
|
+
protected getSimilarProductsRecommendations(query: ProductRecommendationAlgorithmSimilarProductsQuery): Promise<ProductRecommendation[]>;
|
|
20
|
+
protected getTrendingInCategoryRecommendations(query: ProductRecommendationAlgorithmTrendingInCategoryQuery): Promise<ProductRecommendation[]>;
|
|
21
|
+
protected getRelatedProductsRecommendations(query: ProductRecommendationAlgorithmRelatedProductsQuery): Promise<ProductRecommendation[]>;
|
|
22
|
+
protected getPopularProductsRecommendations(query: ProductRecommendationAlgorithmPopuplarProductsQuery): Promise<ProductRecommendation[]>;
|
|
23
|
+
protected getTopPicksProductsRecommendations(query: ProductRecommendationAlgorithmTopPicksProductsQuery): Promise<ProductRecommendation[]>;
|
|
24
|
+
protected getAlsoViewedProductsRecommendations(query: ProductRecommendationAlgorithmAlsoViewedProductsQuery): Promise<ProductRecommendation[]>;
|
|
25
|
+
protected getResourceName(): string;
|
|
26
|
+
}
|
|
27
|
+
export declare class MulticastProductRecommendationsProvider extends ProductRecommendationsProvider {
|
|
28
|
+
protected providers: Array<ProductRecommendationsProvider>;
|
|
29
|
+
constructor(cache: Cache, requestContext: RequestContext, providers: Array<ProductRecommendationsProvider>);
|
|
30
|
+
getRecommendations(query: ProductRecommendationsQuery): Promise<Result<ProductRecommendation[]>>;
|
|
31
|
+
getCollection(query: ProductRecommendationsByCollectionQuery): Promise<Result<ProductRecommendation[]>>;
|
|
32
|
+
}
|
|
@@ -4,6 +4,8 @@ import type { Client } from '../client/client.js';
|
|
|
4
4
|
export declare const CapabilitiesSchema: z.ZodObject<{
|
|
5
5
|
product: z.ZodBoolean;
|
|
6
6
|
productSearch: z.ZodBoolean;
|
|
7
|
+
productAssociations: z.ZodBoolean;
|
|
8
|
+
productRecommendations: z.ZodBoolean;
|
|
7
9
|
analytics: z.ZodBoolean;
|
|
8
10
|
identity: z.ZodBoolean;
|
|
9
11
|
cart: z.ZodBoolean;
|
|
@@ -108,6 +108,10 @@ export declare const PaymentInstructionIdentifierSchema: z.ZodObject<{
|
|
|
108
108
|
export declare const PickupPointIdentifierSchema: z.ZodObject<{
|
|
109
109
|
key: z.ZodString;
|
|
110
110
|
}, z.core.$loose>;
|
|
111
|
+
export declare const ProductRecommendationIdentifierSchema: z.ZodObject<{
|
|
112
|
+
key: z.ZodString;
|
|
113
|
+
algorithm: z.ZodString;
|
|
114
|
+
}, z.core.$loose>;
|
|
111
115
|
export declare const ProductSearchIdentifierSchema: z.ZodObject<{
|
|
112
116
|
term: z.ZodString;
|
|
113
117
|
facets: z.ZodArray<z.ZodObject<{
|
|
@@ -179,4 +183,5 @@ export type ProductOptionIdentifier = InferType<typeof ProductOptionIdentifierSc
|
|
|
179
183
|
export type ProductOptionValueIdentifier = InferType<typeof ProductOptionValueIdentifierSchema>;
|
|
180
184
|
export type ProductAttributeIdentifier = InferType<typeof ProductAttributeIdentifierSchema>;
|
|
181
185
|
export type ProductAttributeValueIdentifier = InferType<typeof ProductAttributeValueIdentifierSchema>;
|
|
182
|
-
export type
|
|
186
|
+
export type ProductRecommendationIdentifier = InferType<typeof ProductRecommendationIdentifierSchema>;
|
|
187
|
+
export type IdentifierType = ProductIdentifier | ProductVariantIdentifier | SearchIdentifier | FacetIdentifier | FacetValueIdentifier | CartIdentifier | CartItemIdentifier | PriceIdentifier | CategoryIdentifier | WebStoreIdentifier | InventoryIdentifier | ProductRecommendationIdentifier | FulfillmentCenterIdentifier | IdentityIdentifier | ShippingMethodIdentifier | PaymentMethodIdentifier | AddressIdentifier | PaymentInstructionIdentifier | OrderIdentifier | OrderItemIdentifier | CheckoutIdentifier | CheckoutItemIdentifier | StoreIdentifier | ProductOptionIdentifier | ProductOptionValueIdentifier | PickupPointIdentifier | ProductAttributeIdentifier | ProductAttributeValueIdentifier;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import z from "zod";
|
|
2
|
+
export declare const ProductRecommendationSchema: z.ZodObject<{
|
|
3
|
+
recommendationIdentifier: z.ZodObject<{
|
|
4
|
+
key: z.ZodString;
|
|
5
|
+
algorithm: z.ZodString;
|
|
6
|
+
}, z.z.core.$loose>;
|
|
7
|
+
product: z.ZodObject<{
|
|
8
|
+
key: z.ZodString;
|
|
9
|
+
}, z.z.core.$loose>;
|
|
10
|
+
}, z.z.core.$loose>;
|
|
11
|
+
export type ProductRecommendation = z.infer<typeof ProductRecommendationSchema>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import z from "zod";
|
|
2
|
+
export declare const ProductAssociationsGetAccessoriesQuerySchema: z.ZodObject<{
|
|
3
|
+
forProductVariant: z.ZodObject<{
|
|
4
|
+
sku: z.ZodString;
|
|
5
|
+
}, z.z.core.$loose>;
|
|
6
|
+
numberOfAccessories: z.ZodNumber;
|
|
7
|
+
}, z.z.core.$loose>;
|
|
8
|
+
export declare const ProductAssociationsGetSparepartsQuerySchema: z.ZodObject<{
|
|
9
|
+
forProductVariant: z.ZodObject<{
|
|
10
|
+
sku: z.ZodString;
|
|
11
|
+
}, z.z.core.$loose>;
|
|
12
|
+
}, z.z.core.$loose>;
|
|
13
|
+
export declare const ProductAssociationsGetReplacementsQuerySchema: z.ZodObject<{
|
|
14
|
+
forProductVariant: z.ZodObject<{
|
|
15
|
+
sku: z.ZodString;
|
|
16
|
+
}, z.z.core.$loose>;
|
|
17
|
+
}, z.z.core.$loose>;
|
|
18
|
+
export type ProductAssociationsGetAccessoriesQuery = z.infer<typeof ProductAssociationsGetAccessoriesQuerySchema>;
|
|
19
|
+
export type ProductAssociationsGetSparepartsQuery = z.infer<typeof ProductAssociationsGetSparepartsQuerySchema>;
|
|
20
|
+
export type ProductAssociationsGetReplacementsQuery = z.infer<typeof ProductAssociationsGetReplacementsQuerySchema>;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import z from "zod";
|
|
2
|
+
import type { InferType } from "../../zod-utils.js";
|
|
3
|
+
export declare const ProductRecommendationBaseQuerySchema: z.ZodObject<{
|
|
4
|
+
numberOfRecommendations: z.ZodNumber;
|
|
5
|
+
labels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
6
|
+
}, z.z.core.$loose>;
|
|
7
|
+
export declare const ProductRecommendationsByCollectionQuerySchema: z.ZodObject<{
|
|
8
|
+
numberOfRecommendations: z.ZodNumber;
|
|
9
|
+
labels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
10
|
+
collectionName: z.ZodString;
|
|
11
|
+
sourceProduct: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
12
|
+
key: z.ZodString;
|
|
13
|
+
}, z.z.core.$loose>>>;
|
|
14
|
+
sourceCategory: z.ZodOptional<z.ZodObject<{
|
|
15
|
+
key: z.ZodString;
|
|
16
|
+
}, z.z.core.$loose>>;
|
|
17
|
+
}, z.z.core.$loose>;
|
|
18
|
+
export declare const ProductRecommendationProductBasedBaseQuerySchema: z.ZodObject<{
|
|
19
|
+
numberOfRecommendations: z.ZodNumber;
|
|
20
|
+
labels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
21
|
+
sourceProduct: z.ZodObject<{
|
|
22
|
+
key: z.ZodString;
|
|
23
|
+
}, z.z.core.$loose>;
|
|
24
|
+
}, z.z.core.$loose>;
|
|
25
|
+
export declare const ProductRecommendationAlgorithmFrequentlyBoughtTogetherQuerySchema: z.ZodObject<{
|
|
26
|
+
numberOfRecommendations: z.ZodNumber;
|
|
27
|
+
labels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
28
|
+
sourceProduct: z.ZodObject<{
|
|
29
|
+
key: z.ZodString;
|
|
30
|
+
}, z.z.core.$loose>;
|
|
31
|
+
algorithm: z.ZodLiteral<"frequentlyBoughtTogether">;
|
|
32
|
+
}, z.z.core.$loose>;
|
|
33
|
+
export declare const ProductRecommendationAlgorithmSimilarProductsQuerySchema: z.ZodObject<{
|
|
34
|
+
numberOfRecommendations: z.ZodNumber;
|
|
35
|
+
labels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
36
|
+
sourceProduct: z.ZodObject<{
|
|
37
|
+
key: z.ZodString;
|
|
38
|
+
}, z.z.core.$loose>;
|
|
39
|
+
algorithm: z.ZodLiteral<"similar">;
|
|
40
|
+
}, z.z.core.$loose>;
|
|
41
|
+
export declare const ProductRecommendationAlgorithmRelatedProductsQuerySchema: z.ZodObject<{
|
|
42
|
+
numberOfRecommendations: z.ZodNumber;
|
|
43
|
+
labels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
44
|
+
sourceProduct: z.ZodObject<{
|
|
45
|
+
key: z.ZodString;
|
|
46
|
+
}, z.z.core.$loose>;
|
|
47
|
+
algorithm: z.ZodLiteral<"related">;
|
|
48
|
+
}, z.z.core.$loose>;
|
|
49
|
+
export declare const ProductRecommendationAlgorithmTrendingInCategoryQuerySchema: z.ZodObject<{
|
|
50
|
+
numberOfRecommendations: z.ZodNumber;
|
|
51
|
+
labels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
52
|
+
algorithm: z.ZodLiteral<"trendingInCategory">;
|
|
53
|
+
sourceCategory: z.ZodObject<{
|
|
54
|
+
key: z.ZodString;
|
|
55
|
+
}, z.z.core.$loose>;
|
|
56
|
+
}, z.z.core.$loose>;
|
|
57
|
+
export declare const ProductRecommendationAlgorithmPopuplarProductsQuerySchema: z.ZodObject<{
|
|
58
|
+
numberOfRecommendations: z.ZodNumber;
|
|
59
|
+
labels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
60
|
+
algorithm: z.ZodLiteral<"popular">;
|
|
61
|
+
}, z.z.core.$loose>;
|
|
62
|
+
export declare const ProductRecommendationAlgorithmTopPicksProductsQuerySchema: z.ZodObject<{
|
|
63
|
+
numberOfRecommendations: z.ZodNumber;
|
|
64
|
+
labels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
65
|
+
algorithm: z.ZodLiteral<"topPicks">;
|
|
66
|
+
}, z.z.core.$loose>;
|
|
67
|
+
export declare const ProductRecommendationAlgorithmAlsoViewedProductsQuerySchema: z.ZodObject<{
|
|
68
|
+
numberOfRecommendations: z.ZodNumber;
|
|
69
|
+
labels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
70
|
+
sourceProduct: z.ZodObject<{
|
|
71
|
+
key: z.ZodString;
|
|
72
|
+
}, z.z.core.$loose>;
|
|
73
|
+
algorithm: z.ZodLiteral<"alsoViewed">;
|
|
74
|
+
}, z.z.core.$loose>;
|
|
75
|
+
export declare const ProductRecommendationsQuerySchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
76
|
+
numberOfRecommendations: z.ZodNumber;
|
|
77
|
+
labels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
78
|
+
sourceProduct: z.ZodObject<{
|
|
79
|
+
key: z.ZodString;
|
|
80
|
+
}, z.z.core.$loose>;
|
|
81
|
+
algorithm: z.ZodLiteral<"frequentlyBoughtTogether">;
|
|
82
|
+
}, z.z.core.$loose>, z.ZodObject<{
|
|
83
|
+
numberOfRecommendations: z.ZodNumber;
|
|
84
|
+
labels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
85
|
+
algorithm: z.ZodLiteral<"trendingInCategory">;
|
|
86
|
+
sourceCategory: z.ZodObject<{
|
|
87
|
+
key: z.ZodString;
|
|
88
|
+
}, z.z.core.$loose>;
|
|
89
|
+
}, z.z.core.$loose>, z.ZodObject<{
|
|
90
|
+
numberOfRecommendations: z.ZodNumber;
|
|
91
|
+
labels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
92
|
+
sourceProduct: z.ZodObject<{
|
|
93
|
+
key: z.ZodString;
|
|
94
|
+
}, z.z.core.$loose>;
|
|
95
|
+
algorithm: z.ZodLiteral<"similar">;
|
|
96
|
+
}, z.z.core.$loose>, z.ZodObject<{
|
|
97
|
+
numberOfRecommendations: z.ZodNumber;
|
|
98
|
+
labels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
99
|
+
sourceProduct: z.ZodObject<{
|
|
100
|
+
key: z.ZodString;
|
|
101
|
+
}, z.z.core.$loose>;
|
|
102
|
+
algorithm: z.ZodLiteral<"related">;
|
|
103
|
+
}, z.z.core.$loose>, z.ZodObject<{
|
|
104
|
+
numberOfRecommendations: z.ZodNumber;
|
|
105
|
+
labels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
106
|
+
algorithm: z.ZodLiteral<"popular">;
|
|
107
|
+
}, z.z.core.$loose>, z.ZodObject<{
|
|
108
|
+
numberOfRecommendations: z.ZodNumber;
|
|
109
|
+
labels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
110
|
+
algorithm: z.ZodLiteral<"topPicks">;
|
|
111
|
+
}, z.z.core.$loose>, z.ZodObject<{
|
|
112
|
+
numberOfRecommendations: z.ZodNumber;
|
|
113
|
+
labels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
114
|
+
sourceProduct: z.ZodObject<{
|
|
115
|
+
key: z.ZodString;
|
|
116
|
+
}, z.z.core.$loose>;
|
|
117
|
+
algorithm: z.ZodLiteral<"alsoViewed">;
|
|
118
|
+
}, z.z.core.$loose>], "algorithm">;
|
|
119
|
+
export type ProductRecommendationsQuery = InferType<typeof ProductRecommendationsQuerySchema>;
|
|
120
|
+
export type ProductRecommendationsByCollectionQuery = InferType<typeof ProductRecommendationsByCollectionQuerySchema>;
|
|
121
|
+
export type ProductRecommendationAlgorithmTopPicksProductsQuery = InferType<typeof ProductRecommendationAlgorithmTopPicksProductsQuerySchema>;
|
|
122
|
+
export type ProductRecommendationAlgorithmPopuplarProductsQuery = InferType<typeof ProductRecommendationAlgorithmPopuplarProductsQuerySchema>;
|
|
123
|
+
export type ProductRecommendationAlgorithmTrendingInCategoryQuery = InferType<typeof ProductRecommendationAlgorithmTrendingInCategoryQuerySchema>;
|
|
124
|
+
export type ProductRecommendationAlgorithmRelatedProductsQuery = InferType<typeof ProductRecommendationAlgorithmRelatedProductsQuerySchema>;
|
|
125
|
+
export type ProductRecommendationAlgorithmSimilarProductsQuery = InferType<typeof ProductRecommendationAlgorithmSimilarProductsQuerySchema>;
|
|
126
|
+
export type ProductRecommendationAlgorithmFrequentlyBoughtTogetherQuery = InferType<typeof ProductRecommendationAlgorithmFrequentlyBoughtTogetherQuerySchema>;
|
|
127
|
+
export type ProductRecommendationAlgorithmAlsoViewedProductsQuery = InferType<typeof ProductRecommendationAlgorithmAlsoViewedProductsQuerySchema>;
|