@reactionary/algolia 0.10.24 → 0.10.26
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/capabilities/analytics.capability.js +4 -4
- package/capabilities/product-recommendations.capability.js +11 -6
- package/capabilities/product-search.capability.js +1 -1
- package/core/index-utils.js +2 -2
- package/factories/product-search/product-search.factory.js +5 -0
- package/package.json +2 -2
- package/schema/configuration.schema.js +2 -1
- package/src/capabilities/product-recommendations.capability.d.ts +11 -9
- package/src/core/index-utils.d.ts +2 -1
- package/src/factories/product-search/product-search.factory.d.ts +2 -1
- package/src/schema/configuration.schema.d.ts +1 -0
- package/src/schema/search.schema.d.ts +10 -0
- package/test/client-builder-product-search-extension.example.js +2 -1
|
@@ -27,7 +27,7 @@ class AlgoliaAnalyticsCapability extends AnalyticsCapability {
|
|
|
27
27
|
eventName: "addToCart",
|
|
28
28
|
eventType: "conversion",
|
|
29
29
|
eventSubtype: "addToCart",
|
|
30
|
-
index: getProductIndexNameForLocale(this.config.indexName, this.context.languageContext.locale),
|
|
30
|
+
index: getProductIndexNameForLocale(this.config.indexName, this.context.languageContext.locale, this.config),
|
|
31
31
|
objectIDs: [event.product.key],
|
|
32
32
|
userToken: event.personalizationProfile?.identifier.key || "anonymous",
|
|
33
33
|
authenticatedUserToken: this.authenticatedUserToken,
|
|
@@ -45,7 +45,7 @@ class AlgoliaAnalyticsCapability extends AnalyticsCapability {
|
|
|
45
45
|
const algoliaEvent = {
|
|
46
46
|
eventName: "click",
|
|
47
47
|
eventType: "click",
|
|
48
|
-
index: getProductIndexNameForLocale(this.config.indexName, this.context.languageContext.locale),
|
|
48
|
+
index: getProductIndexNameForLocale(this.config.indexName, this.context.languageContext.locale, this.config),
|
|
49
49
|
objectIDs: [event.product.key],
|
|
50
50
|
userToken: event.personalizationProfile?.identifier.key || "anonymous",
|
|
51
51
|
authenticatedUserToken: this.authenticatedUserToken,
|
|
@@ -64,7 +64,7 @@ class AlgoliaAnalyticsCapability extends AnalyticsCapability {
|
|
|
64
64
|
const algoliaEvent = {
|
|
65
65
|
eventName: "view",
|
|
66
66
|
eventType: "view",
|
|
67
|
-
index: getProductIndexNameForLocale(this.config.indexName, this.context.languageContext.locale),
|
|
67
|
+
index: getProductIndexNameForLocale(this.config.indexName, this.context.languageContext.locale, this.config),
|
|
68
68
|
objectIDs: event.products.map((x) => x.key),
|
|
69
69
|
userToken: event.personalizationProfile?.identifier.key || "anonymous",
|
|
70
70
|
authenticatedUserToken: this.authenticatedUserToken
|
|
@@ -81,7 +81,7 @@ class AlgoliaAnalyticsCapability extends AnalyticsCapability {
|
|
|
81
81
|
eventName: "purchase",
|
|
82
82
|
eventType: "conversion",
|
|
83
83
|
eventSubtype: "purchase",
|
|
84
|
-
index: getProductIndexNameForLocale(this.config.indexName, this.context.languageContext.locale),
|
|
84
|
+
index: getProductIndexNameForLocale(this.config.indexName, this.context.languageContext.locale, this.config),
|
|
85
85
|
objectIDs: event.order.items.map((x) => x.variant.sku),
|
|
86
86
|
userToken: event.personalizationProfile?.identifier.key || "anonymous",
|
|
87
87
|
authenticatedUserToken: this.authenticatedUserToken
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ProductRecommendationsCapability,
|
|
3
3
|
ProductSearchResultItemVariantSchema,
|
|
4
|
-
ImageSchema
|
|
4
|
+
ImageSchema,
|
|
5
|
+
ProductSearchResultItemComplianceDataSchema
|
|
5
6
|
} from "@reactionary/core";
|
|
6
7
|
import {
|
|
7
8
|
liteClient
|
|
@@ -44,7 +45,7 @@ class AlgoliaProductRecommendationsCapability extends ProductRecommendationsCapa
|
|
|
44
45
|
const response = await this.client.getRecommendations({
|
|
45
46
|
requests: [
|
|
46
47
|
{
|
|
47
|
-
indexName: getProductIndexNameForLocale(this.config.indexName, this.context.languageContext.locale),
|
|
48
|
+
indexName: getProductIndexNameForLocale(this.config.indexName, this.context.languageContext.locale, this.config),
|
|
48
49
|
model: "bought-together",
|
|
49
50
|
objectID: query.sourceProduct.key,
|
|
50
51
|
maxRecommendations: query.numberOfRecommendations,
|
|
@@ -77,7 +78,7 @@ class AlgoliaProductRecommendationsCapability extends ProductRecommendationsCapa
|
|
|
77
78
|
const response = await this.client.getRecommendations({
|
|
78
79
|
requests: [
|
|
79
80
|
{
|
|
80
|
-
indexName: getProductIndexNameForLocale(this.config.indexName, this.context.languageContext.locale),
|
|
81
|
+
indexName: getProductIndexNameForLocale(this.config.indexName, this.context.languageContext.locale, this.config),
|
|
81
82
|
model: "looking-similar",
|
|
82
83
|
objectID: query.sourceProduct.key,
|
|
83
84
|
maxRecommendations: query.numberOfRecommendations,
|
|
@@ -110,7 +111,7 @@ class AlgoliaProductRecommendationsCapability extends ProductRecommendationsCapa
|
|
|
110
111
|
const response = await this.client.getRecommendations({
|
|
111
112
|
requests: [
|
|
112
113
|
{
|
|
113
|
-
indexName: getProductIndexNameForLocale(this.config.indexName, this.context.languageContext.locale),
|
|
114
|
+
indexName: getProductIndexNameForLocale(this.config.indexName, this.context.languageContext.locale, this.config),
|
|
114
115
|
model: "related-products",
|
|
115
116
|
objectID: query.sourceProduct.key,
|
|
116
117
|
maxRecommendations: query.numberOfRecommendations,
|
|
@@ -143,7 +144,7 @@ class AlgoliaProductRecommendationsCapability extends ProductRecommendationsCapa
|
|
|
143
144
|
const response = await this.client.getRecommendations({
|
|
144
145
|
requests: [
|
|
145
146
|
{
|
|
146
|
-
indexName: getProductIndexNameForLocale(this.config.indexName, this.context.languageContext.locale),
|
|
147
|
+
indexName: getProductIndexNameForLocale(this.config.indexName, this.context.languageContext.locale, this.config),
|
|
147
148
|
model: "trending-items",
|
|
148
149
|
facetName: "categories",
|
|
149
150
|
facetValue: query.sourceCategory.key,
|
|
@@ -195,10 +196,14 @@ class AlgoliaProductRecommendationsCapability extends ProductRecommendationsCapa
|
|
|
195
196
|
identifier: { key: body.objectID },
|
|
196
197
|
name: body.name || body.objectID,
|
|
197
198
|
slug: body.slug || body.objectID,
|
|
198
|
-
variants: [...body.variants || []].map((variant) => this.parseVariant(variant, body))
|
|
199
|
+
variants: [...body.variants || []].map((variant) => this.parseVariant(variant, body)),
|
|
200
|
+
complianceData: this.parseComplianceData(body)
|
|
199
201
|
};
|
|
200
202
|
return product;
|
|
201
203
|
}
|
|
204
|
+
parseComplianceData(body) {
|
|
205
|
+
return body.complianceData ?? ProductSearchResultItemComplianceDataSchema.parse({});
|
|
206
|
+
}
|
|
202
207
|
parseVariant(variant, product) {
|
|
203
208
|
const result = ProductSearchResultItemVariantSchema.parse({
|
|
204
209
|
variant: {
|
|
@@ -44,7 +44,7 @@ class AlgoliaProductSearchCapability extends ProductSearchCapability {
|
|
|
44
44
|
rulesContext.push(...payload.personalizationProfile.segments.map((s) => `segment_${s}`));
|
|
45
45
|
}
|
|
46
46
|
return {
|
|
47
|
-
indexName: getProductIndexNameForLocale(this.config.indexName, this.context.languageContext.locale),
|
|
47
|
+
indexName: getProductIndexNameForLocale(this.config.indexName, this.context.languageContext.locale, this.config),
|
|
48
48
|
query: payload.search.term,
|
|
49
49
|
page: payload.search.paginationOptions.pageNumber - 1,
|
|
50
50
|
hitsPerPage: payload.search.paginationOptions.pageSize,
|
package/core/index-utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
function getProductIndexNameForLocale(baseIndexName, locale) {
|
|
1
|
+
function getProductIndexNameForLocale(baseIndexName, locale, config) {
|
|
2
2
|
const localeShortCode = locale.split("-")[0];
|
|
3
|
-
if (localeShortCode === "en") {
|
|
3
|
+
if (localeShortCode === "en" && config.useBaseIndexNameForEnglishLocale) {
|
|
4
4
|
return baseIndexName;
|
|
5
5
|
}
|
|
6
6
|
return `${baseIndexName}_${localeShortCode}`;
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
ImageSchema,
|
|
5
5
|
ProductSearchResultFacetSchema,
|
|
6
6
|
ProductSearchResultFacetValueSchema,
|
|
7
|
+
ProductSearchResultItemComplianceDataSchema,
|
|
7
8
|
ProductSearchResultItemVariantSchema
|
|
8
9
|
} from "@reactionary/core";
|
|
9
10
|
class AlgoliaProductSearchFactory {
|
|
@@ -61,11 +62,15 @@ class AlgoliaProductSearchFactory {
|
|
|
61
62
|
};
|
|
62
63
|
return this.productSearchResultSchema.parse(result);
|
|
63
64
|
}
|
|
65
|
+
parseComplianceData(data) {
|
|
66
|
+
return data.complianceData ?? ProductSearchResultItemComplianceDataSchema.parse({});
|
|
67
|
+
}
|
|
64
68
|
parseSingle(body) {
|
|
65
69
|
return {
|
|
66
70
|
identifier: { key: body.objectID },
|
|
67
71
|
name: body.name || body.objectID,
|
|
68
72
|
slug: body.slug || body.objectID,
|
|
73
|
+
complianceData: this.parseComplianceData(body),
|
|
69
74
|
variants: [...body.variants || []].map(
|
|
70
75
|
(variant) => this.parseVariant(variant, body)
|
|
71
76
|
)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reactionary/algolia",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.26",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"types": "./src/index.d.ts",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"url": "git+https://github.com/Solteq/reactionary.git"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@reactionary/core": "0.10.
|
|
12
|
+
"@reactionary/core": "0.10.26",
|
|
13
13
|
"zod": "4.1.9",
|
|
14
14
|
"algoliasearch": "^5.48.0"
|
|
15
15
|
},
|
|
@@ -3,7 +3,8 @@ const AlgoliaConfigurationSchema = z.looseObject({
|
|
|
3
3
|
appId: z.string(),
|
|
4
4
|
apiKey: z.string(),
|
|
5
5
|
indexName: z.string(),
|
|
6
|
-
useRecommendationsForBots: z.boolean().default(false).meta({ description: "Whether to use recommendations for bot traffic. By default, recommendations are not used for bots to save on API costs, but enabling this can provide a better experience for bot traffic such as search engine crawlers." })
|
|
6
|
+
useRecommendationsForBots: z.boolean().default(false).meta({ description: "Whether to use recommendations for bot traffic. By default, recommendations are not used for bots to save on API costs, but enabling this can provide a better experience for bot traffic such as search engine crawlers." }),
|
|
7
|
+
useBaseIndexNameForEnglishLocale: z.boolean().default(true).meta({ description: "Deprecated. When possible, move to all indexes with locale suffix. Whether to use the base name for the English locale. By default, this is enabled.", deprecated: true })
|
|
7
8
|
});
|
|
8
9
|
export {
|
|
9
10
|
AlgoliaConfigurationSchema
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Cache, ProductRecommendationsCapability, type ProductRecommendation, type ProductRecommendationAlgorithmFrequentlyBoughtTogetherQuery, type ProductRecommendationAlgorithmSimilarProductsQuery, type ProductRecommendationAlgorithmRelatedProductsQuery, type ProductRecommendationAlgorithmTrendingInCategoryQuery, type RequestContext, type ProductRecommendationsQuery, type ProductSearchResultItemVariant, type ProductRecommendationBaseQuery } from '@reactionary/core';
|
|
1
|
+
import { type Cache, ProductRecommendationsCapability, type ProductRecommendation, type ProductRecommendationAlgorithmFrequentlyBoughtTogetherQuery, type ProductRecommendationAlgorithmSimilarProductsQuery, type ProductRecommendationAlgorithmRelatedProductsQuery, type ProductRecommendationAlgorithmTrendingInCategoryQuery, type RequestContext, type ProductRecommendationsQuery, type ProductSearchResultItem, type ProductSearchResultItemVariant, type ProductRecommendationBaseQuery, type ProductSearchResultItemComplianceData } from '@reactionary/core';
|
|
2
2
|
import { type RecommendationsResults, type RecommendSearchParams, type LiteClient } from 'algoliasearch/lite';
|
|
3
3
|
import type { AlgoliaConfiguration } from '../schema/configuration.schema.js';
|
|
4
4
|
import type { AlgoliaProductRecommendationIdentifier } from '../schema/product-recommendation.schema.js';
|
|
@@ -83,6 +83,14 @@ export declare class AlgoliaProductRecommendationsCapability extends ProductReco
|
|
|
83
83
|
};
|
|
84
84
|
} | undefined;
|
|
85
85
|
}[];
|
|
86
|
+
complianceData?: {
|
|
87
|
+
ce_marking: boolean;
|
|
88
|
+
weee_symbol: boolean;
|
|
89
|
+
energy_class?: string | undefined;
|
|
90
|
+
garan_duration?: number | undefined;
|
|
91
|
+
is_organic?: boolean | undefined;
|
|
92
|
+
organic_certification_type?: string | undefined;
|
|
93
|
+
} | undefined;
|
|
86
94
|
};
|
|
87
95
|
} & {
|
|
88
96
|
_?: never;
|
|
@@ -91,13 +99,7 @@ export declare class AlgoliaProductRecommendationsCapability extends ProductReco
|
|
|
91
99
|
* Maps Algolia recommendation results to ProductRecommendation format
|
|
92
100
|
*/
|
|
93
101
|
protected parseSingle(hit: AlgoliaNativeRecord, recommendationIdentifier: AlgoliaProductRecommendationIdentifier): ProductRecommendation;
|
|
94
|
-
protected parseSearchResultItem(body: AlgoliaNativeRecord):
|
|
95
|
-
|
|
96
|
-
key: string;
|
|
97
|
-
};
|
|
98
|
-
name: string;
|
|
99
|
-
slug: string;
|
|
100
|
-
variants: ProductSearchResultItemVariant[];
|
|
101
|
-
};
|
|
102
|
+
protected parseSearchResultItem(body: AlgoliaNativeRecord): ProductSearchResultItem;
|
|
103
|
+
protected parseComplianceData(body: AlgoliaNativeRecord): ProductSearchResultItemComplianceData;
|
|
102
104
|
protected parseVariant(variant: AlgoliaNativeVariant, product: AlgoliaNativeRecord): ProductSearchResultItemVariant;
|
|
103
105
|
}
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import type { AlgoliaConfiguration } from "../schema/configuration.schema.js";
|
|
2
|
+
export declare function getProductIndexNameForLocale(baseIndexName: string, locale: string, config: AlgoliaConfiguration): string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AnyProductSearchResultSchema, FacetIdentifier, FacetValueIdentifier, ProductSearchFactory, ProductSearchQueryByTerm, ProductSearchResultFacet, ProductSearchResultFacetValue, ProductSearchResultItem, ProductSearchResultItemVariant, RequestContext } from '@reactionary/core';
|
|
1
|
+
import type { AnyProductSearchResultSchema, FacetIdentifier, FacetValueIdentifier, ProductSearchFactory, ProductSearchQueryByTerm, ProductSearchResultFacet, ProductSearchResultFacetValue, ProductSearchResultItem, ProductSearchResultItemComplianceData, ProductSearchResultItemVariant, RequestContext } from '@reactionary/core';
|
|
2
2
|
import type * as z from 'zod';
|
|
3
3
|
import type { SearchResponse } from 'algoliasearch';
|
|
4
4
|
import type { AlgoliaNativeRecord, AlgoliaNativeVariant } from '../../schema/search.schema.js';
|
|
@@ -7,6 +7,7 @@ export declare class AlgoliaProductSearchFactory<TProductSearchResultSchema exte
|
|
|
7
7
|
readonly productSearchResultSchema: TProductSearchResultSchema;
|
|
8
8
|
constructor(productSearchResultSchema: TProductSearchResultSchema);
|
|
9
9
|
parseSearchResult(_context: RequestContext, data: unknown, query: ProductSearchQueryByTerm): z.output<TProductSearchResultSchema>;
|
|
10
|
+
protected parseComplianceData(data: AlgoliaNativeRecord): ProductSearchResultItemComplianceData;
|
|
10
11
|
protected parseSingle(body: AlgoliaNativeRecord): ProductSearchResultItem;
|
|
11
12
|
protected parseVariant(variant: AlgoliaNativeVariant, product: AlgoliaNativeRecord): ProductSearchResultItemVariant;
|
|
12
13
|
protected parseFacet(facetIdentifier: FacetIdentifier, facetValues: Record<string, number>): ProductSearchResultFacet;
|
|
@@ -4,5 +4,6 @@ export declare const AlgoliaConfigurationSchema: z.ZodObject<{
|
|
|
4
4
|
apiKey: z.ZodString;
|
|
5
5
|
indexName: z.ZodString;
|
|
6
6
|
useRecommendationsForBots: z.ZodDefault<z.ZodBoolean>;
|
|
7
|
+
useBaseIndexNameForEnglishLocale: z.ZodDefault<z.ZodBoolean>;
|
|
7
8
|
}, z.core.$loose>;
|
|
8
9
|
export type AlgoliaConfiguration = z.infer<typeof AlgoliaConfigurationSchema>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ProductSearchResultItemComplianceData } from '@reactionary/core';
|
|
1
2
|
import * as z from 'zod';
|
|
2
3
|
export declare const AlgoliaProductSearchIdentifierSchema: z.ZodObject<{
|
|
3
4
|
term: z.ZodString;
|
|
@@ -35,6 +36,14 @@ export declare const AlgoliaProductSearchResultSchema: z.ZodObject<{
|
|
|
35
36
|
}, z.core.$loose>;
|
|
36
37
|
name: z.ZodString;
|
|
37
38
|
slug: z.ZodString;
|
|
39
|
+
complianceData: z.ZodOptional<z.ZodObject<{
|
|
40
|
+
ce_marking: z.ZodDefault<z.ZodBoolean>;
|
|
41
|
+
weee_symbol: z.ZodDefault<z.ZodBoolean>;
|
|
42
|
+
energy_class: z.ZodOptional<z.ZodString>;
|
|
43
|
+
garan_duration: z.ZodOptional<z.ZodNumber>;
|
|
44
|
+
is_organic: z.ZodOptional<z.ZodBoolean>;
|
|
45
|
+
organic_certification_type: z.ZodOptional<z.ZodString>;
|
|
46
|
+
}, z.core.$loose>>;
|
|
38
47
|
variants: z.ZodArray<z.ZodObject<{
|
|
39
48
|
variant: z.ZodObject<{
|
|
40
49
|
sku: z.ZodString;
|
|
@@ -116,4 +125,5 @@ export interface AlgoliaNativeRecord {
|
|
|
116
125
|
slug?: string;
|
|
117
126
|
name?: string;
|
|
118
127
|
variants: Array<AlgoliaNativeVariant>;
|
|
128
|
+
complianceData?: ProductSearchResultItemComplianceData;
|
|
119
129
|
}
|
|
@@ -34,7 +34,8 @@ const config = {
|
|
|
34
34
|
appId: "ALGOLIA_APP_ID",
|
|
35
35
|
apiKey: "ALGOLIA_API_KEY",
|
|
36
36
|
indexName: "ALGOLIA_INDEX",
|
|
37
|
-
useRecommendationsForBots: false
|
|
37
|
+
useRecommendationsForBots: false,
|
|
38
|
+
useBaseIndexNameForEnglishLocale: true
|
|
38
39
|
};
|
|
39
40
|
const client = new ClientBuilder(createInitialRequestContext()).withCache(new NoOpCache()).withCapability(
|
|
40
41
|
withAlgoliaCapabilities(config, {
|