@reactionary/source 0.3.16 → 0.3.18
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 +2 -2
- package/core/src/initialization.ts +2 -2
- package/core/src/providers/price.provider.ts +2 -1
- package/core/src/schemas/models/cart.model.ts +7 -2
- package/core/src/schemas/models/identifiers.model.ts +12 -8
- package/core/src/schemas/models/price.model.ts +12 -0
- package/examples/node/package.json +7 -7
- package/examples/node/src/capabilities/cart.spec.ts +97 -15
- package/examples/node/src/capabilities/category.spec.ts +27 -32
- package/examples/node/src/capabilities/checkout.spec.ts +5 -5
- package/examples/node/src/capabilities/identity.spec.ts +6 -2
- package/examples/node/src/capabilities/inventory.spec.ts +1 -1
- package/examples/node/src/capabilities/price.spec.ts +7 -7
- package/examples/node/src/utils.ts +4 -1
- package/package.json +3 -3
- package/providers/algolia/src/providers/product-search.provider.ts +19 -14
- package/providers/commercetools/src/core/client.ts +112 -9
- package/providers/commercetools/src/core/token-cache.ts +4 -5
- package/providers/commercetools/src/providers/cart.provider.ts +76 -11
- package/providers/commercetools/src/providers/inventory.provider.ts +5 -7
- package/providers/commercetools/src/providers/price.provider.ts +17 -30
- package/providers/commercetools/src/schema/configuration.schema.ts +4 -0
- package/providers/commercetools/src/schema/session.schema.ts +3 -1
- package/providers/fake/src/providers/cart.provider.ts +1 -0
- package/providers/fake/src/providers/price.provider.ts +54 -95
- package/providers/medusa/src/providers/cart.provider.ts +159 -70
- package/providers/medusa/src/providers/category.provider.ts +35 -23
- package/providers/medusa/src/providers/checkout.provider.ts +78 -41
- package/providers/medusa/src/providers/order-search.provider.ts +21 -10
- package/providers/medusa/src/providers/price.provider.ts +18 -9
- package/providers/medusa/src/providers/product-recommendations.provider.ts +10 -6
- package/providers/medusa/src/providers/product-search.provider.ts +19 -10
- package/providers/medusa/src/providers/product.provider.ts +20 -12
- package/providers/medusa/src/providers/profile.provider.ts +38 -13
- package/providers/meilisearch/src/providers/order-search.provider.ts +17 -12
- package/providers/meilisearch/src/providers/product-recommendations.provider.ts +10 -11
- package/providers/meilisearch/src/providers/product-search.provider.ts +23 -18
|
@@ -79,6 +79,14 @@ export class MedusaProfileProvider extends ProfileProvider {
|
|
|
79
79
|
return success(model);
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
+
protected updatePayload(payload: ProfileMutationUpdate) {
|
|
83
|
+
const updateData: any = {};
|
|
84
|
+
if (payload.phone !== undefined) {
|
|
85
|
+
updateData.phone = payload.phone;
|
|
86
|
+
}
|
|
87
|
+
return updateData;
|
|
88
|
+
}
|
|
89
|
+
|
|
82
90
|
@Reactionary({
|
|
83
91
|
inputSchema: ProfileMutationUpdateSchema,
|
|
84
92
|
outputSchema: ProfileSchema,
|
|
@@ -98,14 +106,16 @@ export class MedusaProfileProvider extends ProfileProvider {
|
|
|
98
106
|
|
|
99
107
|
const customer = customerResponse.customer;
|
|
100
108
|
|
|
101
|
-
const updatedResponse = await client.store.customer.update({
|
|
102
|
-
phone: payload.phone ?? customer.phone,
|
|
103
|
-
}, { fields: this.includedFields.join(',') });
|
|
109
|
+
const updatedResponse = await client.store.customer.update(this.updatePayload(payload), { fields: this.includedFields.join(',') });
|
|
104
110
|
|
|
105
111
|
const model = this.parseSingle(updatedResponse.customer);
|
|
106
112
|
return success(model);
|
|
107
113
|
}
|
|
108
114
|
|
|
115
|
+
protected addShippingAddressPayload(payload: ProfileMutationAddShippingAddress) {
|
|
116
|
+
return this.createMedusaAddress(payload.address);
|
|
117
|
+
}
|
|
118
|
+
|
|
109
119
|
@Reactionary({
|
|
110
120
|
inputSchema: ProfileMutationAddShippingAddressSchema,
|
|
111
121
|
outputSchema: ProfileSchema,
|
|
@@ -115,7 +125,6 @@ export class MedusaProfileProvider extends ProfileProvider {
|
|
|
115
125
|
|
|
116
126
|
const client = await this.medusaApi.getClient();
|
|
117
127
|
|
|
118
|
-
const medusaAddress = this.createMedusaAddress(payload.address);
|
|
119
128
|
|
|
120
129
|
// check if any address with the same nickName exists
|
|
121
130
|
const customer = await client.store.customer.retrieve({ fields: this.includedFields.join(',') });
|
|
@@ -133,7 +142,7 @@ export class MedusaProfileProvider extends ProfileProvider {
|
|
|
133
142
|
});
|
|
134
143
|
}
|
|
135
144
|
|
|
136
|
-
const response = await client.store.customer.createAddress(
|
|
145
|
+
const response = await client.store.customer.createAddress(this.addShippingAddressPayload(payload), { fields: this.includedFields.join(',') });
|
|
137
146
|
if (!response.customer) {
|
|
138
147
|
return error<InvalidInputError>({
|
|
139
148
|
type: 'InvalidInput',
|
|
@@ -145,6 +154,10 @@ export class MedusaProfileProvider extends ProfileProvider {
|
|
|
145
154
|
return success(model);
|
|
146
155
|
}
|
|
147
156
|
|
|
157
|
+
protected updateShippingAddressPayload(payload: ProfileMutationUpdateShippingAddress) {
|
|
158
|
+
return this.createMedusaAddress(payload.address);
|
|
159
|
+
}
|
|
160
|
+
|
|
148
161
|
@Reactionary({
|
|
149
162
|
inputSchema: ProfileMutationUpdateShippingAddressSchema,
|
|
150
163
|
outputSchema: ProfileSchema,
|
|
@@ -162,8 +175,6 @@ export class MedusaProfileProvider extends ProfileProvider {
|
|
|
162
175
|
});
|
|
163
176
|
}
|
|
164
177
|
|
|
165
|
-
const medusaAddress = this.createMedusaAddress(payload.address);
|
|
166
|
-
|
|
167
178
|
const existingAddress = customer.customer.addresses.find(addr => addr.address_name === payload.address.identifier.nickName);
|
|
168
179
|
if (!existingAddress) {
|
|
169
180
|
return error<NotFoundError>({
|
|
@@ -172,7 +183,7 @@ export class MedusaProfileProvider extends ProfileProvider {
|
|
|
172
183
|
});
|
|
173
184
|
}
|
|
174
185
|
|
|
175
|
-
const response = await client.store.customer.updateAddress(existingAddress.id,
|
|
186
|
+
const response = await client.store.customer.updateAddress(existingAddress.id, this.updateShippingAddressPayload(payload), { fields: this.includedFields.join(',') });
|
|
176
187
|
if (!response.customer) {
|
|
177
188
|
return error<InvalidInputError>({
|
|
178
189
|
type: 'InvalidInput',
|
|
@@ -226,6 +237,12 @@ export class MedusaProfileProvider extends ProfileProvider {
|
|
|
226
237
|
}
|
|
227
238
|
|
|
228
239
|
|
|
240
|
+
protected makeShippingAddressDefaultPayload(payload: ProfileMutationMakeShippingAddressDefault) {
|
|
241
|
+
return {
|
|
242
|
+
is_default_shipping: true
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
229
246
|
@Reactionary({
|
|
230
247
|
inputSchema: ProfileMutationMakeShippingAddressDefaultSchema,
|
|
231
248
|
outputSchema: ProfileSchema,
|
|
@@ -251,15 +268,23 @@ export class MedusaProfileProvider extends ProfileProvider {
|
|
|
251
268
|
});
|
|
252
269
|
}
|
|
253
270
|
|
|
254
|
-
const response = await client.store.customer.updateAddress(
|
|
255
|
-
|
|
256
|
-
|
|
271
|
+
const response = await client.store.customer.updateAddress(
|
|
272
|
+
existingAddress.id,
|
|
273
|
+
this.makeShippingAddressDefaultPayload(payload),
|
|
274
|
+
{ fields: this.includedFields.join(',') }
|
|
257
275
|
);
|
|
258
276
|
|
|
259
277
|
const model = this.parseSingle(response.customer!);
|
|
260
278
|
return success(model);
|
|
261
279
|
}
|
|
262
280
|
|
|
281
|
+
|
|
282
|
+
protected setBillingAddressPayload(payload: ProfileMutationSetBillingAddress) {
|
|
283
|
+
const newAddr = this.createMedusaAddress(payload.address);
|
|
284
|
+
newAddr.is_default_billing = true;
|
|
285
|
+
return newAddr;
|
|
286
|
+
}
|
|
287
|
+
|
|
263
288
|
@Reactionary({
|
|
264
289
|
inputSchema: ProfileMutationSetBillingAddressSchema,
|
|
265
290
|
outputSchema: ProfileSchema,
|
|
@@ -289,9 +314,9 @@ export class MedusaProfileProvider extends ProfileProvider {
|
|
|
289
314
|
}
|
|
290
315
|
|
|
291
316
|
|
|
292
|
-
const newAddr = this.createMedusaAddress(payload.address);
|
|
293
|
-
newAddr.is_default_billing = true;
|
|
294
317
|
|
|
318
|
+
|
|
319
|
+
const newAddr = this.setBillingAddressPayload(payload);
|
|
295
320
|
// two scenarios: Either we already have a billing addres, in which case we update it, or we dont and we need to create it.
|
|
296
321
|
const existingBillingAddress = customer.addresses.find(addr => addr.is_default_billing);
|
|
297
322
|
if (existingBillingAddress) {
|
|
@@ -52,17 +52,7 @@ export class MeilisearchOrderSearchProvider extends OrderSearchProvider {
|
|
|
52
52
|
this.config = config;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
inputSchema: OrderSearchQueryByTermSchema,
|
|
57
|
-
outputSchema: OrderSearchResultSchema,
|
|
58
|
-
})
|
|
59
|
-
public async queryByTerm(payload: OrderSearchQueryByTerm): Promise<Result<OrderSearchResult>> {
|
|
60
|
-
const client = new MeiliSearch({
|
|
61
|
-
host: this.config.apiUrl,
|
|
62
|
-
apiKey: this.config.apiKey,
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
const index = client.index(this.config.orderIndexName);
|
|
55
|
+
protected queryByTermPayload(payload: OrderSearchQueryByTerm): SearchParams {
|
|
66
56
|
|
|
67
57
|
const filters: string[] = [];
|
|
68
58
|
|
|
@@ -103,10 +93,25 @@ export class MeilisearchOrderSearchProvider extends OrderSearchProvider {
|
|
|
103
93
|
filter: filters.length > 0 ? filters.join(' AND ') : undefined,
|
|
104
94
|
sort: ['orderDateTimestamp:desc'],
|
|
105
95
|
};
|
|
96
|
+
return searchOptions
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@Reactionary({
|
|
100
|
+
inputSchema: OrderSearchQueryByTermSchema,
|
|
101
|
+
outputSchema: OrderSearchResultSchema,
|
|
102
|
+
})
|
|
103
|
+
public async queryByTerm(payload: OrderSearchQueryByTerm): Promise<Result<OrderSearchResult>> {
|
|
104
|
+
const client = new MeiliSearch({
|
|
105
|
+
host: this.config.apiUrl,
|
|
106
|
+
apiKey: this.config.apiKey,
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
const index = client.index(this.config.orderIndexName);
|
|
110
|
+
|
|
106
111
|
|
|
107
112
|
const remote = await index.search<MeilisearchNativeOrderRecord>(
|
|
108
113
|
payload.search.term || '',
|
|
109
|
-
|
|
114
|
+
this.queryByTermPayload(payload)
|
|
110
115
|
);
|
|
111
116
|
|
|
112
117
|
const result = this.parsePaginatedResult(remote, payload) as OrderSearchResult;
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
type ProductSearchResultItemVariant,
|
|
10
10
|
ProductSearchResultItemVariantSchema,
|
|
11
11
|
} from '@reactionary/core';
|
|
12
|
-
import { MeiliSearch, type Hits, type RecordAny, type SearchParams, type SearchResponse } from 'meilisearch';
|
|
12
|
+
import { MeiliSearch, type Hits, type RecordAny, type SearchParams, type SearchResponse, type SearchSimilarDocumentsParams } from 'meilisearch';
|
|
13
13
|
import type { MeilisearchConfiguration } from '../schema/configuration.schema.js';
|
|
14
14
|
import type { MeilisearchNativeRecord, MeilisearchNativeVariant } from '../schema/index.js';
|
|
15
15
|
|
|
@@ -32,6 +32,14 @@ export class MeilisearchProductRecommendationsProvider extends ProductRecommenda
|
|
|
32
32
|
this.config = config;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
protected getSimilarProductsRecommendationsPayload(query: ProductRecommendationAlgorithmSimilarProductsQuery): SearchSimilarDocumentsParams {
|
|
36
|
+
return {
|
|
37
|
+
id: query.sourceProduct.key,
|
|
38
|
+
limit: query.numberOfRecommendations,
|
|
39
|
+
embedder: this.config.useAIEmbedding,
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
35
43
|
/**
|
|
36
44
|
* Get similar product recommendations
|
|
37
45
|
* Uses semantic search to find visually or data-wise similar products
|
|
@@ -52,16 +60,7 @@ export class MeilisearchProductRecommendationsProvider extends ProductRecommenda
|
|
|
52
60
|
}
|
|
53
61
|
|
|
54
62
|
try {
|
|
55
|
-
const
|
|
56
|
-
limit: query.numberOfRecommendations,
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
const response = await index.searchSimilarDocuments<MeilisearchNativeRecord>({
|
|
60
|
-
id: query.sourceProduct.key,
|
|
61
|
-
limit: query.numberOfRecommendations,
|
|
62
|
-
embedder: this.config.useAIEmbedding,
|
|
63
|
-
});
|
|
64
|
-
|
|
63
|
+
const response = await index.searchSimilarDocuments<MeilisearchNativeRecord>(this.getSimilarProductsRecommendationsPayload(query));
|
|
65
64
|
|
|
66
65
|
return this.parseRecommendations(response, 'similar');
|
|
67
66
|
} catch (error) {
|
|
@@ -36,23 +36,7 @@ export class MeilisearchSearchProvider extends ProductSearchProvider {
|
|
|
36
36
|
this.config = config;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
inputSchema: ProductSearchQueryByTermSchema,
|
|
41
|
-
outputSchema: ProductSearchResultSchema,
|
|
42
|
-
cache: true,
|
|
43
|
-
cacheTimeToLiveInSeconds: 300,
|
|
44
|
-
currencyDependentCaching: false,
|
|
45
|
-
localeDependentCaching: true
|
|
46
|
-
})
|
|
47
|
-
public override async queryByTerm(
|
|
48
|
-
payload: ProductSearchQueryByTerm
|
|
49
|
-
): Promise<Result<ProductSearchResult>> {
|
|
50
|
-
const client = new MeiliSearch({
|
|
51
|
-
host: this.config.apiUrl,
|
|
52
|
-
apiKey: this.config.apiKey,
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
const index = client.index(this.config.indexName);
|
|
39
|
+
protected queryByTermPayload(payload: ProductSearchQueryByTerm) {
|
|
56
40
|
|
|
57
41
|
const facetsThatAreNotCategory = payload.search.facets.filter(x => x.facet.key !== 'categories');
|
|
58
42
|
const categoryFacet = payload.search.facets.find(x => x.facet.key === 'categories') || payload.search.categoryFilter;
|
|
@@ -88,8 +72,29 @@ export class MeilisearchSearchProvider extends ProductSearchProvider {
|
|
|
88
72
|
embedder: this.config.useAIEmbedding
|
|
89
73
|
};
|
|
90
74
|
}
|
|
75
|
+
return searchOptions;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
@Reactionary({
|
|
79
|
+
inputSchema: ProductSearchQueryByTermSchema,
|
|
80
|
+
outputSchema: ProductSearchResultSchema,
|
|
81
|
+
cache: true,
|
|
82
|
+
cacheTimeToLiveInSeconds: 300,
|
|
83
|
+
currencyDependentCaching: false,
|
|
84
|
+
localeDependentCaching: true
|
|
85
|
+
})
|
|
86
|
+
public override async queryByTerm(
|
|
87
|
+
payload: ProductSearchQueryByTerm
|
|
88
|
+
): Promise<Result<ProductSearchResult>> {
|
|
89
|
+
const client = new MeiliSearch({
|
|
90
|
+
host: this.config.apiUrl,
|
|
91
|
+
apiKey: this.config.apiKey,
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const index = client.index(this.config.indexName);
|
|
95
|
+
|
|
91
96
|
|
|
92
|
-
const remote = await index.search<MeilisearchNativeRecord>(payload.search.term,
|
|
97
|
+
const remote = await index.search<MeilisearchNativeRecord>(payload.search.term, this.queryByTermPayload(payload) as SearchParams);
|
|
93
98
|
|
|
94
99
|
const result = this.parsePaginatedResult(remote, payload) as MeilisearchProductSearchResult;
|
|
95
100
|
|