@reactionary/source 0.3.18 → 0.6.2
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 +28 -14
- package/core/src/client/client-builder.ts +54 -6
- package/core/src/factories/cart.factory.ts +40 -0
- package/core/src/factories/category.factory.ts +40 -0
- package/core/src/factories/checkout.factory.ts +59 -0
- package/core/src/factories/identity.factory.ts +26 -0
- package/core/src/factories/index.ts +15 -0
- package/core/src/factories/inventory.factory.ts +26 -0
- package/core/src/factories/order-search.factory.ts +33 -0
- package/core/src/factories/order.factory.ts +21 -0
- package/core/src/factories/price.factory.ts +29 -0
- package/core/src/factories/product-associations.factory.ts +30 -0
- package/core/src/factories/product-list.factory.ts +82 -0
- package/core/src/factories/product-reviews.factory.ts +58 -0
- package/core/src/factories/product-search.factory.ts +31 -0
- package/core/src/factories/product.factory.ts +21 -0
- package/core/src/factories/profile.factory.ts +23 -0
- package/core/src/factories/store.factory.ts +21 -0
- package/core/src/index.ts +3 -1
- package/core/src/providers/cart.provider.ts +12 -10
- package/core/src/providers/category.provider.ts +9 -7
- package/core/src/providers/checkout.provider.ts +14 -10
- package/core/src/providers/identity.provider.ts +7 -7
- package/core/src/providers/inventory.provider.ts +4 -4
- package/core/src/providers/order-search.provider.ts +4 -2
- package/core/src/providers/order.provider.ts +4 -4
- package/core/src/providers/price.provider.ts +5 -5
- package/core/src/providers/product-associations.provider.ts +6 -4
- package/core/src/providers/product-list.provider.ts +13 -8
- package/core/src/providers/product-reviews.provider.ts +8 -4
- package/core/src/providers/product-search.provider.ts +15 -28
- package/core/src/providers/product.provider.ts +6 -6
- package/core/src/providers/profile.provider.ts +8 -8
- package/core/src/providers/store.provider.ts +2 -2
- package/core/src/test/client-builder.spec.ts +81 -0
- package/examples/node/package.json +7 -7
- package/examples/node/src/basic/basic-node-provider-model-extension.spec.ts +10 -4
- package/examples/node/src/basic/basic-node-provider-query-extension.spec.ts +8 -2
- package/examples/node/src/basic/basic-node-setup.spec.ts +5 -1
- package/examples/node/src/basic/client-creation.spec.ts +3 -3
- package/examples/node/src/utils.ts +41 -41
- package/examples/node/tsconfig.lib.json +2 -1
- package/package.json +1 -1
- package/providers/algolia/src/core/initialize.ts +76 -21
- package/providers/algolia/src/core/initialize.types.ts +107 -0
- package/providers/algolia/src/factories/index.ts +1 -0
- package/providers/algolia/src/factories/product-search/product-search.factory.ts +182 -0
- package/providers/algolia/src/index.ts +2 -2
- package/providers/algolia/src/providers/analytics.provider.ts +4 -4
- package/providers/algolia/src/providers/product-search.provider.ts +67 -184
- package/providers/algolia/src/schema/capabilities.schema.ts +81 -7
- package/providers/algolia/src/test/analytics.spec.ts +9 -1
- package/providers/algolia/src/test/client-builder-product-search-extension.example.ts +85 -0
- package/providers/commercetools/src/core/capability-descriptors.ts +324 -0
- package/providers/commercetools/src/core/initialize.ts +35 -151
- package/providers/commercetools/src/core/initialize.types.ts +174 -0
- package/providers/commercetools/src/factories/cart/cart.factory.ts +142 -0
- package/providers/commercetools/src/factories/category/category.factory.ts +77 -0
- package/providers/commercetools/src/factories/checkout/checkout-initializer-overrides.example.ts +94 -0
- package/providers/commercetools/src/factories/checkout/checkout.factory.ts +338 -0
- package/providers/commercetools/src/factories/identity/identity.factory.ts +26 -0
- package/providers/commercetools/src/factories/inventory/inventory.factory.ts +49 -0
- package/providers/commercetools/src/factories/order/order.factory.ts +149 -0
- package/providers/commercetools/src/factories/order-search/order-search.factory.ts +108 -0
- package/providers/commercetools/src/factories/price/price.factory.ts +76 -0
- package/providers/commercetools/src/factories/product/product-factory-baseline.example.ts +14 -0
- package/providers/commercetools/src/factories/product/product-factory-schema-and-parse-extension.example.ts +35 -0
- package/providers/commercetools/src/factories/product/product-factory-schema-extension.example.ts +23 -0
- package/providers/commercetools/src/factories/product/product-initializer-factory-extension.example.ts +41 -0
- package/providers/commercetools/src/factories/product/product-provider-custom-method-only.example.ts +47 -0
- package/providers/commercetools/src/factories/product/product-provider-schema-signature-extension.example.ts +61 -0
- package/providers/commercetools/src/factories/product/product.factory.ts +220 -0
- package/providers/commercetools/src/factories/product/utils.example.ts +9 -0
- package/providers/commercetools/src/factories/product-associations/product-associations.factory.ts +103 -0
- package/providers/commercetools/src/factories/product-list/product-list.factory.ts +122 -0
- package/providers/commercetools/src/factories/product-reviews/product-reviews.factory.ts +81 -0
- package/providers/commercetools/src/factories/product-search/product-search.factory.ts +182 -0
- package/providers/commercetools/src/factories/profile/profile.factory.ts +94 -0
- package/providers/commercetools/src/factories/store/store.factory.ts +49 -0
- package/providers/commercetools/src/index.ts +15 -0
- package/providers/commercetools/src/providers/cart.provider.ts +67 -193
- package/providers/commercetools/src/providers/category.provider.ts +24 -64
- package/providers/commercetools/src/providers/checkout.provider.ts +50 -322
- package/providers/commercetools/src/providers/identity.provider.ts +35 -15
- package/providers/commercetools/src/providers/inventory.provider.ts +13 -31
- package/providers/commercetools/src/providers/order-search.provider.ts +16 -110
- package/providers/commercetools/src/providers/order.provider.ts +13 -144
- package/providers/commercetools/src/providers/price.provider.ts +37 -51
- package/providers/commercetools/src/providers/product-associations.provider.ts +39 -104
- package/providers/commercetools/src/providers/product-list.provider.ts +38 -23
- package/providers/commercetools/src/providers/product-reviews.provider.ts +34 -14
- package/providers/commercetools/src/providers/product-search.provider.ts +17 -170
- package/providers/commercetools/src/providers/product.provider.ts +20 -199
- package/providers/commercetools/src/providers/profile.provider.ts +27 -73
- package/providers/commercetools/src/providers/store.provider.ts +13 -31
- package/providers/commercetools/src/schema/capabilities.schema.ts +258 -20
- package/providers/commercetools/src/test/caching.spec.ts +18 -2
- package/providers/commercetools/src/test/client-builder-merge-extensions.example.ts +125 -0
- package/providers/fake/src/core/initialize.ts +213 -44
- package/providers/fake/src/core/initialize.types.ts +164 -0
- package/providers/fake/src/factories/cart/cart.factory.ts +34 -0
- package/providers/fake/src/factories/category/category.factory.ts +40 -0
- package/providers/fake/src/factories/checkout/checkout.factory.ts +53 -0
- package/providers/fake/src/factories/identity/identity.factory.ts +25 -0
- package/providers/fake/src/factories/index.ts +14 -0
- package/providers/fake/src/factories/inventory/inventory.factory.ts +25 -0
- package/providers/fake/src/factories/order/order.factory.ts +22 -0
- package/providers/fake/src/factories/order-search/order-search.factory.ts +27 -0
- package/providers/fake/src/factories/price/price.factory.ts +26 -0
- package/providers/fake/src/factories/product/product.factory.ts +22 -0
- package/providers/fake/src/factories/product-associations/product-associations.factory.ts +25 -0
- package/providers/fake/src/factories/product-reviews/product-reviews.factory.ts +53 -0
- package/providers/fake/src/factories/product-search/product-search.factory.ts +27 -0
- package/providers/fake/src/factories/profile/profile.factory.ts +22 -0
- package/providers/fake/src/factories/store/store.factory.ts +22 -0
- package/providers/fake/src/index.ts +2 -0
- package/providers/fake/src/providers/cart.provider.ts +23 -14
- package/providers/fake/src/providers/category.provider.ts +120 -105
- package/providers/fake/src/providers/checkout.provider.ts +39 -20
- package/providers/fake/src/providers/identity.provider.ts +40 -34
- package/providers/fake/src/providers/inventory.provider.ts +26 -24
- package/providers/fake/src/providers/order-search.provider.ts +38 -30
- package/providers/fake/src/providers/order.provider.ts +21 -37
- package/providers/fake/src/providers/price.provider.ts +42 -34
- package/providers/fake/src/providers/product-associations.provider.ts +23 -10
- package/providers/fake/src/providers/product-reviews.provider.ts +71 -69
- package/providers/fake/src/providers/product-search.provider.ts +43 -70
- package/providers/fake/src/providers/product.provider.ts +34 -32
- package/providers/fake/src/providers/profile.provider.ts +62 -55
- package/providers/fake/src/providers/store.provider.ts +38 -22
- package/providers/fake/src/schema/capabilities.schema.ts +175 -18
- package/providers/fake/src/test/cart.provider.spec.ts +20 -3
- package/providers/fake/src/test/category.provider.spec.ts +4 -1
- package/providers/fake/src/test/checkout.provider.spec.ts +12 -2
- package/providers/fake/src/test/client-builder-product-extension.example.ts +75 -0
- package/providers/fake/src/test/order-search.provider.spec.ts +4 -7
- package/providers/fake/src/test/order.provider.spec.ts +4 -6
- package/providers/fake/src/test/price.provider.spec.ts +3 -1
- package/providers/fake/src/test/product.provider.spec.ts +8 -2
- package/providers/fake/src/test/profile.provider.spec.ts +4 -2
- package/providers/google-analytics/src/core/initialize.ts +37 -12
- package/providers/google-analytics/src/core/initialize.types.ts +47 -0
- package/providers/google-analytics/src/index.ts +1 -0
- package/providers/google-analytics/src/schema/capabilities.schema.ts +31 -5
- package/providers/medusa/src/core/initialize.ts +324 -81
- package/providers/medusa/src/core/initialize.types.ts +184 -0
- package/providers/medusa/src/factories/cart/cart.factory.ts +34 -0
- package/providers/medusa/src/factories/category/category.factory.ts +37 -0
- package/providers/medusa/src/factories/checkout/checkout.factory.ts +50 -0
- package/providers/medusa/src/factories/identity/identity.factory.ts +22 -0
- package/providers/medusa/src/factories/index.ts +12 -0
- package/providers/medusa/src/factories/inventory/inventory.factory.ts +25 -0
- package/providers/medusa/src/factories/order/order.factory.ts +22 -0
- package/providers/medusa/src/factories/order-search/order-search.factory.ts +27 -0
- package/providers/medusa/src/factories/price/price.factory.ts +26 -0
- package/providers/medusa/src/factories/product/product.factory.ts +22 -0
- package/providers/medusa/src/factories/product-associations/product-associations.factory.ts +25 -0
- package/providers/medusa/src/factories/product-search/product-search.factory.ts +27 -0
- package/providers/medusa/src/factories/profile/profile.factory.ts +22 -0
- package/providers/medusa/src/index.ts +2 -0
- package/providers/medusa/src/providers/cart.provider.ts +33 -20
- package/providers/medusa/src/providers/category.provider.ts +30 -12
- package/providers/medusa/src/providers/checkout.provider.ts +42 -17
- package/providers/medusa/src/providers/identity.provider.ts +1 -1
- package/providers/medusa/src/providers/inventory.provider.ts +21 -7
- package/providers/medusa/src/providers/order-search.provider.ts +16 -5
- package/providers/medusa/src/providers/order.provider.ts +17 -5
- package/providers/medusa/src/providers/price.provider.ts +26 -7
- package/providers/medusa/src/providers/product-associations.provider.ts +19 -8
- package/providers/medusa/src/providers/product-search.provider.ts +19 -31
- package/providers/medusa/src/providers/product.provider.ts +47 -11
- package/providers/medusa/src/providers/profile.provider.ts +35 -11
- package/providers/medusa/src/schema/capabilities.schema.ts +229 -18
- package/providers/medusa/src/test/cart.provider.spec.ts +18 -2
- package/providers/medusa/src/test/category.provider.spec.ts +4 -1
- package/providers/medusa/src/test/checkout.spec.ts +9 -9
- package/providers/medusa/src/test/inventory.provider.spec.ts +3 -1
- package/providers/medusa/src/test/large-cart.provider.spec.ts +8 -2
- package/providers/medusa/src/test/price.provider.spec.ts +8 -1
- package/providers/medusa/src/test/product.provider.spec.ts +3 -1
- package/providers/medusa/src/test/search.provider.spec.ts +16 -3
- package/providers/meilisearch/src/core/initialize.ts +88 -21
- package/providers/meilisearch/src/core/initialize.types.ts +119 -0
- package/providers/meilisearch/src/factories/index.ts +2 -0
- package/providers/meilisearch/src/factories/order-search/order-search.factory.ts +27 -0
- package/providers/meilisearch/src/factories/product-search/product-search.factory.ts +27 -0
- package/providers/meilisearch/src/index.ts +2 -0
- package/providers/meilisearch/src/providers/index.ts +1 -0
- package/providers/meilisearch/src/providers/order-search.provider.ts +21 -6
- package/providers/meilisearch/src/providers/product-search.provider.ts +24 -8
- package/providers/meilisearch/src/schema/capabilities.schema.ts +95 -8
|
@@ -1,43 +1,24 @@
|
|
|
1
1
|
import type {
|
|
2
|
-
ProductSearchFacetResult as CTProductSearchFacetResult,
|
|
3
|
-
ProductSearchFacetResultBucket as CTProductSearchFacetResultBucket,
|
|
4
|
-
ProductVariant as CTProductVariant,
|
|
5
|
-
ProductPagedSearchResponse,
|
|
6
|
-
ProductProjection,
|
|
7
2
|
ProductSearchFacetExpression,
|
|
8
3
|
} from '@commercetools/platform-sdk';
|
|
9
4
|
import type {
|
|
10
5
|
Cache,
|
|
11
6
|
FacetIdentifier,
|
|
12
7
|
FacetValueIdentifier,
|
|
13
|
-
|
|
8
|
+
ProductSearchFactory,
|
|
9
|
+
ProductSearchFactoryOutput,
|
|
10
|
+
ProductSearchFactoryWithOutput,
|
|
14
11
|
ProductSearchQueryByTerm,
|
|
15
12
|
ProductSearchQueryCreateNavigationFilter,
|
|
16
|
-
ProductSearchResult,
|
|
17
|
-
ProductSearchResultFacet,
|
|
18
|
-
ProductSearchResultFacetValue,
|
|
19
|
-
ProductSearchResultItem,
|
|
20
|
-
ProductSearchResultItemVariant,
|
|
21
|
-
ProductVariantIdentifier,
|
|
22
|
-
ProductVariantOption,
|
|
23
13
|
RequestContext,
|
|
24
14
|
Result,
|
|
25
|
-
SearchIdentifier,
|
|
26
15
|
} from '@reactionary/core';
|
|
27
16
|
import {
|
|
28
|
-
FacetIdentifierSchema,
|
|
29
17
|
FacetValueIdentifierSchema,
|
|
30
|
-
ImageSchema,
|
|
31
|
-
ProductOptionIdentifierSchema,
|
|
32
18
|
ProductSearchProvider,
|
|
33
19
|
ProductSearchQueryByTermSchema,
|
|
34
20
|
ProductSearchQueryCreateNavigationFilterSchema,
|
|
35
|
-
ProductSearchResultFacetSchema,
|
|
36
|
-
ProductSearchResultFacetValueSchema,
|
|
37
|
-
ProductSearchResultItemVariantSchema,
|
|
38
21
|
ProductSearchResultSchema,
|
|
39
|
-
ProductVariantIdentifierSchema,
|
|
40
|
-
ProductVariantOptionSchema,
|
|
41
22
|
Reactionary,
|
|
42
23
|
success,
|
|
43
24
|
} from '@reactionary/core';
|
|
@@ -46,23 +27,29 @@ import type { CommercetoolsConfiguration } from '../schema/configuration.schema.
|
|
|
46
27
|
import createDebug from 'debug';
|
|
47
28
|
import type { CommercetoolsAPI } from '../core/client.js';
|
|
48
29
|
import { CommercetoolsCategoryLookupSchema, CommercetoolsResolveCategoryQueryByKeySchema, type CommercetoolsCategoryLookup, type CommercetoolsResolveCategoryQueryById, type CommercetoolsResolveCategoryQueryByKey } from '../schema/commercetools.schema.js';
|
|
30
|
+
import type { CommercetoolsProductSearchFactory } from '../factories/product-search/product-search.factory.js';
|
|
49
31
|
|
|
50
32
|
const debug = createDebug('reactionary:commercetools:search');
|
|
51
33
|
|
|
52
|
-
export class CommercetoolsSearchProvider
|
|
34
|
+
export class CommercetoolsSearchProvider<
|
|
35
|
+
TFactory extends ProductSearchFactory = CommercetoolsProductSearchFactory,
|
|
36
|
+
> extends ProductSearchProvider<ProductSearchFactoryOutput<TFactory>> {
|
|
53
37
|
protected config: CommercetoolsConfiguration;
|
|
54
38
|
protected commercetools: CommercetoolsAPI;
|
|
39
|
+
protected factory: ProductSearchFactoryWithOutput<TFactory>;
|
|
55
40
|
|
|
56
41
|
constructor(
|
|
57
42
|
config: CommercetoolsConfiguration,
|
|
58
43
|
cache: Cache,
|
|
59
44
|
context: RequestContext,
|
|
60
|
-
commercetools: CommercetoolsAPI
|
|
45
|
+
commercetools: CommercetoolsAPI,
|
|
46
|
+
factory: ProductSearchFactoryWithOutput<TFactory>,
|
|
61
47
|
) {
|
|
62
48
|
super(cache, context);
|
|
63
49
|
|
|
64
50
|
this.config = config;
|
|
65
51
|
this.commercetools = commercetools;
|
|
52
|
+
this.factory = factory;
|
|
66
53
|
}
|
|
67
54
|
|
|
68
55
|
protected async getClient() {
|
|
@@ -275,7 +262,7 @@ export class CommercetoolsSearchProvider extends ProductSearchProvider {
|
|
|
275
262
|
})
|
|
276
263
|
public override async queryByTerm(
|
|
277
264
|
payload: ProductSearchQueryByTerm
|
|
278
|
-
): Promise<Result<
|
|
265
|
+
): Promise<Result<ProductSearchFactoryOutput<TFactory>>> {
|
|
279
266
|
const client = await this.getClient();
|
|
280
267
|
|
|
281
268
|
const facetsToReturn = await this.getFacetsToReturn(payload);
|
|
@@ -327,10 +314,11 @@ export class CommercetoolsSearchProvider extends ProductSearchProvider {
|
|
|
327
314
|
.execute();
|
|
328
315
|
|
|
329
316
|
const responseBody = response.body;
|
|
330
|
-
const result = this.
|
|
317
|
+
const result = this.factory.parseSearchResult(
|
|
318
|
+
this.context,
|
|
331
319
|
responseBody,
|
|
332
|
-
payload
|
|
333
|
-
)
|
|
320
|
+
payload,
|
|
321
|
+
);
|
|
334
322
|
|
|
335
323
|
|
|
336
324
|
// ok, we have to patch up the categories facet to have the category keys instead of ids
|
|
@@ -358,7 +346,7 @@ export class CommercetoolsSearchProvider extends ProductSearchProvider {
|
|
|
358
346
|
return success(result);
|
|
359
347
|
}
|
|
360
348
|
|
|
361
|
-
protected async patchCategoryFacetValues(result:
|
|
349
|
+
protected async patchCategoryFacetValues(result: ProductSearchFactoryOutput<TFactory>) {
|
|
362
350
|
const categoryFacet = result.facets.find(
|
|
363
351
|
(f) => f.identifier.key === 'categories'
|
|
364
352
|
);
|
|
@@ -384,145 +372,4 @@ export class CommercetoolsSearchProvider extends ProductSearchProvider {
|
|
|
384
372
|
}
|
|
385
373
|
|
|
386
374
|
|
|
387
|
-
protected parseSingle(body: ProductProjection) {
|
|
388
|
-
const identifier = { key: body.id };
|
|
389
|
-
const name = body.name[this.context.languageContext.locale] || body.id;
|
|
390
|
-
const slug = body.slug?.[this.context.languageContext.locale] || body.id;
|
|
391
|
-
const variants = [body.masterVariant, ...body.variants].map((variant) =>
|
|
392
|
-
this.parseVariant(variant, body)
|
|
393
|
-
);
|
|
394
|
-
|
|
395
|
-
const product = {
|
|
396
|
-
identifier,
|
|
397
|
-
name,
|
|
398
|
-
slug,
|
|
399
|
-
variants,
|
|
400
|
-
} satisfies ProductSearchResultItem;
|
|
401
|
-
|
|
402
|
-
return product;
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
protected parsePaginatedResult(
|
|
406
|
-
body: ProductPagedSearchResponse,
|
|
407
|
-
query: ProductSearchQueryByTerm
|
|
408
|
-
) {
|
|
409
|
-
const identifier = {
|
|
410
|
-
...query.search,
|
|
411
|
-
} satisfies SearchIdentifier;
|
|
412
|
-
|
|
413
|
-
const products: ProductSearchResultItem[] = body.results.map((p) =>
|
|
414
|
-
this.parseSingle(p.productProjection!)
|
|
415
|
-
);
|
|
416
|
-
const facets: ProductSearchResultFacet[] = [];
|
|
417
|
-
|
|
418
|
-
for (const facet of body.facets) {
|
|
419
|
-
const facetIdentifier = FacetIdentifierSchema.parse({
|
|
420
|
-
key: facet.name,
|
|
421
|
-
} satisfies Partial<FacetIdentifier>);
|
|
422
|
-
|
|
423
|
-
const candidateFacet = this.parseFacet(facetIdentifier, facet);
|
|
424
|
-
if (candidateFacet.values.length > 0) {
|
|
425
|
-
facets.push(candidateFacet);
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
const result = {
|
|
430
|
-
identifier,
|
|
431
|
-
pageNumber: (Math.ceil(body.offset / body.limit) || 0) + 1,
|
|
432
|
-
pageSize: body.limit,
|
|
433
|
-
totalCount: body.total || 0,
|
|
434
|
-
totalPages: Math.ceil((body.total || 0) / body.limit || 0) + 1,
|
|
435
|
-
items: products,
|
|
436
|
-
facets,
|
|
437
|
-
} satisfies ProductSearchResult;
|
|
438
|
-
|
|
439
|
-
return result;
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
/**
|
|
443
|
-
* See version 0.0.81 for ProductProjection based facet parsing
|
|
444
|
-
* @param facetIdentifier
|
|
445
|
-
* @param facetValue
|
|
446
|
-
* @returns
|
|
447
|
-
*/
|
|
448
|
-
protected parseFacet(
|
|
449
|
-
facetIdentifier: FacetIdentifier,
|
|
450
|
-
facet: CTProductSearchFacetResult
|
|
451
|
-
): ProductSearchResultFacet {
|
|
452
|
-
const result: ProductSearchResultFacet =
|
|
453
|
-
ProductSearchResultFacetSchema.parse({
|
|
454
|
-
identifier: facetIdentifier,
|
|
455
|
-
name: facet.name,
|
|
456
|
-
values: [],
|
|
457
|
-
});
|
|
458
|
-
|
|
459
|
-
const distinctFacet = facet as CTProductSearchFacetResultBucket;
|
|
460
|
-
if (distinctFacet) {
|
|
461
|
-
distinctFacet.buckets.forEach((bucket) => {
|
|
462
|
-
const facetValueIdentifier = FacetValueIdentifierSchema.parse({
|
|
463
|
-
facet: facetIdentifier,
|
|
464
|
-
key: bucket.key,
|
|
465
|
-
} satisfies Partial<FacetValueIdentifier>);
|
|
466
|
-
|
|
467
|
-
result.values.push(
|
|
468
|
-
this.parseFacetValue(facetValueIdentifier, bucket.key, bucket.count)
|
|
469
|
-
);
|
|
470
|
-
});
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
return result;
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
protected parseFacetValue(
|
|
477
|
-
facetValueIdentifier: FacetValueIdentifier,
|
|
478
|
-
label: string,
|
|
479
|
-
count: number
|
|
480
|
-
): ProductSearchResultFacetValue {
|
|
481
|
-
|
|
482
|
-
return ProductSearchResultFacetValueSchema.parse({
|
|
483
|
-
identifier: facetValueIdentifier,
|
|
484
|
-
name: label,
|
|
485
|
-
count: count,
|
|
486
|
-
active: false,
|
|
487
|
-
} satisfies Partial<ProductSearchResultFacetValue>);
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
protected parseVariant(
|
|
491
|
-
variant: CTProductVariant,
|
|
492
|
-
product: ProductProjection
|
|
493
|
-
): ProductSearchResultItemVariant {
|
|
494
|
-
const sourceImage = variant.images?.[0];
|
|
495
|
-
|
|
496
|
-
const img = ImageSchema.parse({
|
|
497
|
-
sourceUrl: sourceImage?.url || '',
|
|
498
|
-
height: sourceImage?.dimensions.h || undefined,
|
|
499
|
-
width: sourceImage?.dimensions.w || undefined,
|
|
500
|
-
altText:
|
|
501
|
-
sourceImage?.label ||
|
|
502
|
-
product.name[this.context.languageContext.locale] ||
|
|
503
|
-
undefined,
|
|
504
|
-
});
|
|
505
|
-
|
|
506
|
-
const mappedOptions =
|
|
507
|
-
variant.attributes
|
|
508
|
-
?.filter((x) => x.name === 'Color')
|
|
509
|
-
.map((opt) =>
|
|
510
|
-
ProductVariantOptionSchema.parse({
|
|
511
|
-
identifier: ProductOptionIdentifierSchema.parse({
|
|
512
|
-
key: opt.name,
|
|
513
|
-
} satisfies Partial<ProductOptionIdentifier>),
|
|
514
|
-
name: opt.value || '',
|
|
515
|
-
} satisfies Partial<ProductVariantOption>)
|
|
516
|
-
) || [];
|
|
517
|
-
|
|
518
|
-
const mappedOption = mappedOptions?.[0];
|
|
519
|
-
|
|
520
|
-
return ProductSearchResultItemVariantSchema.parse({
|
|
521
|
-
variant: ProductVariantIdentifierSchema.parse({
|
|
522
|
-
sku: variant.sku || '',
|
|
523
|
-
} satisfies ProductVariantIdentifier),
|
|
524
|
-
image: img,
|
|
525
|
-
options: mappedOption,
|
|
526
|
-
} satisfies Partial<ProductSearchResultItemVariant>);
|
|
527
|
-
}
|
|
528
375
|
}
|
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
import {
|
|
2
|
-
ImageSchema,
|
|
3
|
-
ProductAttributeIdentifierSchema,
|
|
4
|
-
ProductAttributeSchema,
|
|
5
|
-
ProductAttributeValueIdentifierSchema,
|
|
6
|
-
ProductAttributeValueSchema,
|
|
7
2
|
ProductProvider,
|
|
8
3
|
ProductQueryByIdSchema,
|
|
9
4
|
ProductQueryBySKUSchema,
|
|
@@ -12,48 +7,34 @@ import {
|
|
|
12
7
|
Reactionary,
|
|
13
8
|
success,
|
|
14
9
|
error,
|
|
10
|
+
type ProductFactory,
|
|
11
|
+
type ProductFactoryOutput,
|
|
12
|
+
type ProductFactoryWithOutput,
|
|
15
13
|
} from '@reactionary/core';
|
|
16
14
|
import type { CommercetoolsConfiguration } from '../schema/configuration.schema.js';
|
|
17
15
|
import type {
|
|
18
|
-
ProductProjection,
|
|
19
|
-
ProductVariant as CTProductVariant,
|
|
20
|
-
Attribute as CTAttribute,
|
|
21
|
-
} from '@commercetools/platform-sdk';
|
|
22
|
-
import type {
|
|
23
|
-
Product,
|
|
24
|
-
ProductVariant,
|
|
25
16
|
ProductQueryById,
|
|
26
17
|
ProductQueryBySKU,
|
|
27
18
|
ProductQueryBySlug,
|
|
28
|
-
ProductVariantIdentifier,
|
|
29
19
|
RequestContext,
|
|
30
|
-
ProductAttribute,
|
|
31
|
-
ProductAttributeIdentifier,
|
|
32
|
-
ProductAttributeValue,
|
|
33
|
-
ProductAttributeValueIdentifier,
|
|
34
|
-
ProductIdentifier,
|
|
35
|
-
ProductVariantOption,
|
|
36
|
-
ProductOptionIdentifier,
|
|
37
20
|
Result,
|
|
38
21
|
} from '@reactionary/core';
|
|
39
|
-
import type { Cache
|
|
22
|
+
import type { Cache } from '@reactionary/core';
|
|
40
23
|
import type { CommercetoolsAPI } from '../core/client.js';
|
|
41
24
|
import type { NotFoundError } from '@reactionary/core';
|
|
25
|
+
import type { CommercetoolsProductFactory } from '../factories/product/product.factory.js';
|
|
42
26
|
|
|
43
|
-
export class CommercetoolsProductProvider
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
27
|
+
export class CommercetoolsProductProvider<
|
|
28
|
+
TFactory extends ProductFactory = CommercetoolsProductFactory
|
|
29
|
+
> extends ProductProvider<ProductFactoryOutput<TFactory>> {
|
|
47
30
|
constructor(
|
|
48
|
-
config: CommercetoolsConfiguration,
|
|
49
31
|
cache: Cache,
|
|
50
32
|
context: RequestContext,
|
|
51
|
-
|
|
33
|
+
protected config: CommercetoolsConfiguration,
|
|
34
|
+
protected commercetools: CommercetoolsAPI,
|
|
35
|
+
protected factory: ProductFactoryWithOutput<TFactory>
|
|
52
36
|
) {
|
|
53
37
|
super(cache, context);
|
|
54
|
-
|
|
55
|
-
this.config = config;
|
|
56
|
-
this.commercetools = commercetools;
|
|
57
38
|
}
|
|
58
39
|
|
|
59
40
|
protected async getClient() {
|
|
@@ -73,13 +54,14 @@ export class CommercetoolsProductProvider extends ProductProvider {
|
|
|
73
54
|
})
|
|
74
55
|
public override async getById(
|
|
75
56
|
payload: ProductQueryById
|
|
76
|
-
): Promise<Result<
|
|
57
|
+
): Promise<Result<ProductFactoryOutput<TFactory>>> {
|
|
77
58
|
const client = await this.getClient();
|
|
78
59
|
const remote = await client
|
|
79
60
|
.withKey({ key: payload.identifier.key })
|
|
80
61
|
.get()
|
|
81
62
|
.execute();
|
|
82
|
-
|
|
63
|
+
|
|
64
|
+
const value = this.factory.parseProduct(this.context, remote.body);
|
|
83
65
|
|
|
84
66
|
return success(value);
|
|
85
67
|
}
|
|
@@ -94,7 +76,7 @@ export class CommercetoolsProductProvider extends ProductProvider {
|
|
|
94
76
|
})
|
|
95
77
|
public override async getBySlug(
|
|
96
78
|
payload: ProductQueryBySlug
|
|
97
|
-
): Promise<Result<
|
|
79
|
+
): Promise<Result<ProductFactoryOutput<TFactory>, NotFoundError>> {
|
|
98
80
|
const client = await this.getClient();
|
|
99
81
|
|
|
100
82
|
const remote = await client
|
|
@@ -113,7 +95,7 @@ export class CommercetoolsProductProvider extends ProductProvider {
|
|
|
113
95
|
identifier: payload.slug,
|
|
114
96
|
});
|
|
115
97
|
}
|
|
116
|
-
const result = this.
|
|
98
|
+
const result = this.factory.parseProduct(this.context, remote.body.results[0]);
|
|
117
99
|
|
|
118
100
|
return success(result);
|
|
119
101
|
}
|
|
@@ -128,7 +110,7 @@ export class CommercetoolsProductProvider extends ProductProvider {
|
|
|
128
110
|
})
|
|
129
111
|
public override async getBySKU(
|
|
130
112
|
payload: ProductQueryBySKU
|
|
131
|
-
): Promise<Result<
|
|
113
|
+
): Promise<Result<ProductFactoryOutput<TFactory>>> {
|
|
132
114
|
const client = await this.getClient();
|
|
133
115
|
|
|
134
116
|
const remote = await client
|
|
@@ -142,171 +124,10 @@ export class CommercetoolsProductProvider extends ProductProvider {
|
|
|
142
124
|
})
|
|
143
125
|
.execute();
|
|
144
126
|
|
|
145
|
-
|
|
127
|
+
// PAIN: the lack of knowing the non-generic type signature of the factory (the scopedown to CT Product Provider)
|
|
128
|
+
// this is due to the Typescript construct for ProductFactoryOutput<TFactory>
|
|
129
|
+
const result = this.factory.parseProduct(this.context, remote.body.results[0]);
|
|
146
130
|
|
|
147
131
|
return success(result);
|
|
148
132
|
}
|
|
149
|
-
|
|
150
|
-
protected parseSingle(data: ProductProjection): Product {
|
|
151
|
-
const identifier = { key: data.key || data.id } satisfies ProductIdentifier;
|
|
152
|
-
const name = data.name[this.context.languageContext.locale];
|
|
153
|
-
const slug = data.slug[this.context.languageContext.locale];
|
|
154
|
-
|
|
155
|
-
let description = '';
|
|
156
|
-
if (data.description) {
|
|
157
|
-
description = data.description[this.context.languageContext.locale];
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
const variantLevelAttributes =
|
|
161
|
-
data.masterVariant.attributes?.map((x) => this.parseAttribute(x)) || [];
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
const specialAttributes = [
|
|
165
|
-
'reactionaryaccessories',
|
|
166
|
-
'reactionaryspareparts',
|
|
167
|
-
'reactionaryreplacements'
|
|
168
|
-
]
|
|
169
|
-
|
|
170
|
-
const productLevelAttributes =
|
|
171
|
-
data.attributes.filter(x => !specialAttributes.includes(x.name)).map((x) => this.parseAttribute(x)) || [];
|
|
172
|
-
|
|
173
|
-
const sharedAttributes = [
|
|
174
|
-
...productLevelAttributes,
|
|
175
|
-
...variantLevelAttributes,
|
|
176
|
-
];
|
|
177
|
-
const mainVariant = this.parseVariant(data.masterVariant, data);
|
|
178
|
-
|
|
179
|
-
const otherVariants = [];
|
|
180
|
-
for (const variant of data.variants || []) {
|
|
181
|
-
if (variant.id !== data.masterVariant.id) {
|
|
182
|
-
otherVariants.push(this.parseVariant(variant, data));
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
const result = {
|
|
187
|
-
identifier,
|
|
188
|
-
name,
|
|
189
|
-
slug,
|
|
190
|
-
description,
|
|
191
|
-
sharedAttributes,
|
|
192
|
-
mainVariant,
|
|
193
|
-
brand: '',
|
|
194
|
-
longDescription: '',
|
|
195
|
-
manufacturer: '',
|
|
196
|
-
options: [],
|
|
197
|
-
parentCategories: [],
|
|
198
|
-
published: true,
|
|
199
|
-
variants: otherVariants,
|
|
200
|
-
} satisfies Product;
|
|
201
|
-
|
|
202
|
-
return result;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Return true, if the attribute is a defining attribute (ie an option)
|
|
207
|
-
* @param attr a variant attribute
|
|
208
|
-
* @returns true if the attribute is an option
|
|
209
|
-
*/
|
|
210
|
-
protected isVariantAttributeAnOption(attr: CTAttribute): boolean {
|
|
211
|
-
// for now, the assumption is that any variant attribute is a defining attribute (ie an option)
|
|
212
|
-
// ideally this should be verified with the product type.
|
|
213
|
-
return true;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
protected parseVariant(
|
|
217
|
-
variant: CTProductVariant,
|
|
218
|
-
product: ProductProjection
|
|
219
|
-
): ProductVariant {
|
|
220
|
-
const identifier = {
|
|
221
|
-
sku: variant.sku!,
|
|
222
|
-
} satisfies ProductVariantIdentifier;
|
|
223
|
-
|
|
224
|
-
const images = [
|
|
225
|
-
...(variant.images || []).map((img) =>
|
|
226
|
-
ImageSchema.parse({
|
|
227
|
-
sourceUrl: img.url,
|
|
228
|
-
altText: img.label || '',
|
|
229
|
-
width: img.dimensions?.w,
|
|
230
|
-
height: img.dimensions?.h,
|
|
231
|
-
} satisfies Image)
|
|
232
|
-
),
|
|
233
|
-
];
|
|
234
|
-
|
|
235
|
-
const options =
|
|
236
|
-
(variant.attributes ?? [])
|
|
237
|
-
.filter((attr) => this.isVariantAttributeAnOption(attr))
|
|
238
|
-
.map((attr) => {
|
|
239
|
-
const attrVal = this.parseAttributeValue(attr);
|
|
240
|
-
const optionIdentifier: ProductOptionIdentifier = {
|
|
241
|
-
key: attr.name,
|
|
242
|
-
};
|
|
243
|
-
const option: ProductVariantOption = {
|
|
244
|
-
identifier: optionIdentifier,
|
|
245
|
-
name: attr.name,
|
|
246
|
-
value: {
|
|
247
|
-
identifier: {
|
|
248
|
-
key: attrVal.value,
|
|
249
|
-
option: optionIdentifier,
|
|
250
|
-
},
|
|
251
|
-
label: attrVal.label,
|
|
252
|
-
},
|
|
253
|
-
};
|
|
254
|
-
return option;
|
|
255
|
-
}) || [];
|
|
256
|
-
|
|
257
|
-
const result = {
|
|
258
|
-
identifier,
|
|
259
|
-
images,
|
|
260
|
-
barcode: '',
|
|
261
|
-
ean: '',
|
|
262
|
-
gtin: '',
|
|
263
|
-
name: product.name[this.context.languageContext.locale],
|
|
264
|
-
options,
|
|
265
|
-
upc: '',
|
|
266
|
-
} satisfies ProductVariant;
|
|
267
|
-
|
|
268
|
-
return result;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
protected parseAttribute(attr: CTAttribute): ProductAttribute {
|
|
272
|
-
const result = ProductAttributeSchema.parse({
|
|
273
|
-
identifier: ProductAttributeIdentifierSchema.parse({
|
|
274
|
-
key: attr.name,
|
|
275
|
-
} satisfies Partial<ProductAttributeIdentifier>),
|
|
276
|
-
group: '',
|
|
277
|
-
name: attr.name,
|
|
278
|
-
values: [this.parseAttributeValue(attr)],
|
|
279
|
-
} satisfies Partial<ProductAttribute>);
|
|
280
|
-
|
|
281
|
-
return result;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
protected parseAttributeValue(attr: CTAttribute): ProductAttributeValue {
|
|
285
|
-
let attrValue = '';
|
|
286
|
-
if (attr.value && Array.isArray(attr.value)) {
|
|
287
|
-
attrValue = attr.value[0];
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
if (attr.value && typeof attr.value === 'object') {
|
|
291
|
-
if (this.context.languageContext.locale in attr.value) {
|
|
292
|
-
attrValue = attr.value[this.context.languageContext.locale];
|
|
293
|
-
} else {
|
|
294
|
-
attrValue = '-';
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
if (typeof attr.value === 'string') {
|
|
299
|
-
attrValue = attr.value;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
const attrVal = ProductAttributeValueSchema.parse({
|
|
303
|
-
identifier: ProductAttributeValueIdentifierSchema.parse({
|
|
304
|
-
key: attrValue,
|
|
305
|
-
} satisfies Partial<ProductAttributeValueIdentifier>),
|
|
306
|
-
value: String(attrValue),
|
|
307
|
-
label: String(attrValue),
|
|
308
|
-
} satisfies Partial<ProductAttributeValue>);
|
|
309
|
-
|
|
310
|
-
return attrVal;
|
|
311
|
-
}
|
|
312
133
|
}
|