@reactionary/hcl 0.9.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.
Files changed (36) hide show
  1. package/README.md +11 -0
  2. package/capabilities/category.capability.js +170 -0
  3. package/capabilities/product-search.capability.js +89 -0
  4. package/capabilities/product.capability.js +157 -0
  5. package/core/client.js +120 -0
  6. package/core/initialize.js +97 -0
  7. package/core/initialize.types.js +8 -0
  8. package/core/locale-params.js +9 -0
  9. package/factories/category/category.factory.js +60 -0
  10. package/factories/index.js +3 -0
  11. package/factories/product/product.factory.js +154 -0
  12. package/factories/product-search/product-search.factory.js +71 -0
  13. package/index.js +11 -0
  14. package/package.json +14 -0
  15. package/schema/capabilities.schema.js +27 -0
  16. package/schema/category.schema.js +9 -0
  17. package/schema/configuration.schema.js +33 -0
  18. package/schema/hcl.schema.js +0 -0
  19. package/src/capabilities/category.capability.d.ts +15 -0
  20. package/src/capabilities/product-search.capability.d.ts +14 -0
  21. package/src/capabilities/product.capability.d.ts +20 -0
  22. package/src/core/client.d.ts +19 -0
  23. package/src/core/initialize.d.ts +5 -0
  24. package/src/core/initialize.types.d.ts +42 -0
  25. package/src/core/locale-params.d.ts +6 -0
  26. package/src/factories/category/category.factory.d.ts +12 -0
  27. package/src/factories/index.d.ts +3 -0
  28. package/src/factories/product/product.factory.d.ts +8 -0
  29. package/src/factories/product-search/product-search.factory.d.ts +11 -0
  30. package/src/index.d.ts +11 -0
  31. package/src/schema/capabilities.schema.d.ts +63 -0
  32. package/src/schema/category.schema.d.ts +27 -0
  33. package/src/schema/configuration.schema.d.ts +18 -0
  34. package/src/schema/hcl.schema.d.ts +312 -0
  35. package/src/test/test-utils.d.ts +241 -0
  36. package/test/test-utils.js +30 -0
package/README.md ADDED
@@ -0,0 +1,11 @@
1
+ # hcl
2
+
3
+ This library was generated with [Nx](https://nx.dev).
4
+
5
+ ## Building
6
+
7
+ Run `nx build hcl` to build the library.
8
+
9
+ ## Running unit tests
10
+
11
+ Run `nx test hcl` to execute the unit tests via [Vitest](https://vitest.dev/).
@@ -0,0 +1,170 @@
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 {
13
+ CategoryCapability,
14
+ CategoryPaginatedResultSchema,
15
+ CategoryQueryByIdSchema,
16
+ CategoryQueryBySlugSchema,
17
+ CategoryQueryForBreadcrumbSchema,
18
+ CategoryQueryForChildCategoriesSchema,
19
+ CategoryQueryForTopCategoriesSchema,
20
+ CategorySchema,
21
+ Reactionary,
22
+ error,
23
+ success
24
+ } from "@reactionary/core";
25
+ import * as z from "zod";
26
+ import { getLocaleParams } from "../core/locale-params.js";
27
+ class HclCategoryCapability extends CategoryCapability {
28
+ constructor(cache, context, config, client, factory) {
29
+ super(cache, context);
30
+ this.config = config;
31
+ this.client = client;
32
+ this.factory = factory;
33
+ }
34
+ async getById(payload) {
35
+ const { langId } = getLocaleParams(this.config, this.context);
36
+ const response = await this.client.findCategories({
37
+ identifier: [payload.id.key],
38
+ langId
39
+ });
40
+ const data = response.contents?.[0];
41
+ if (!data) {
42
+ return error({ type: "NotFound", identifier: payload.id });
43
+ }
44
+ return success(this.factory.parseCategory(this.context, data));
45
+ }
46
+ async getBySlug(payload) {
47
+ const { langId } = getLocaleParams(this.config, this.context);
48
+ const token = await this.client.resolveSlug(payload.slug, langId);
49
+ if (!token || token.tokenName !== "CategoryToken" || !token.tokenExternalValue) {
50
+ return error({
51
+ type: "NotFound",
52
+ identifier: payload.slug
53
+ });
54
+ }
55
+ const response = await this.client.findCategories({
56
+ // tokenExternalValue is the external identifier (e.g. "LivingRoom").
57
+ // Use identifier= param so the key returned by the factory is consistent.
58
+ identifier: [token.tokenExternalValue],
59
+ langId
60
+ });
61
+ const data = response.contents?.[0];
62
+ if (!data) {
63
+ return error({
64
+ type: "NotFound",
65
+ identifier: payload.slug
66
+ });
67
+ }
68
+ return success(this.factory.parseCategory(this.context, data));
69
+ }
70
+ async getBreadcrumbPathToCategory(payload) {
71
+ const { langId } = getLocaleParams(this.config, this.context);
72
+ const leafResponse = await this.client.findCategories({
73
+ identifier: [payload.id.key],
74
+ langId
75
+ });
76
+ const leafData = leafResponse.contents?.[0];
77
+ if (!leafData) {
78
+ return success([]);
79
+ }
80
+ const parentId = leafData.parentCatalogGroupID;
81
+ const pathSegments = (typeof parentId === "string" ? parentId : parentId?.[0] ?? "").split("/").filter(Boolean);
82
+ const ancestorIds = pathSegments.slice(0, -1);
83
+ const ancestorsResp = ancestorIds.length > 0 ? await this.client.findCategories({ id: ancestorIds, langId }) : { contents: [] };
84
+ const byUniqueId = new Map(
85
+ (ancestorsResp.contents ?? []).map((c) => [c.uniqueID, c])
86
+ );
87
+ const path = [];
88
+ for (const id of ancestorIds) {
89
+ const data = byUniqueId.get(id);
90
+ if (data) {
91
+ path.push(this.factory.parseCategory(this.context, data));
92
+ }
93
+ }
94
+ path.push(this.factory.parseCategory(this.context, leafData));
95
+ return success(path);
96
+ }
97
+ async findChildCategories(payload) {
98
+ const { langId } = getLocaleParams(this.config, this.context);
99
+ const parentResp = await this.client.findCategories({
100
+ identifier: [payload.parentId.key],
101
+ langId
102
+ });
103
+ const parentUniqueId = parentResp.contents?.[0]?.uniqueID;
104
+ if (!parentUniqueId) {
105
+ return error({
106
+ type: "NotFound",
107
+ identifier: payload.parentId
108
+ });
109
+ }
110
+ const response = await this.client.findCategories({
111
+ parentCategoryId: parentUniqueId,
112
+ depthAndLimit: "1,0",
113
+ langId
114
+ });
115
+ const items = response.contents ?? [];
116
+ const paginated = this.factory.parseCategoryPaginatedResult(
117
+ this.context,
118
+ items,
119
+ payload
120
+ );
121
+ return success(paginated);
122
+ }
123
+ async findTopCategories(payload) {
124
+ const { langId } = getLocaleParams(this.config, this.context);
125
+ const response = await this.client.findCategories({
126
+ depthAndLimit: "1,0",
127
+ langId
128
+ });
129
+ const items = response.contents ?? [];
130
+ const paginated = this.factory.parseCategoryPaginatedResult(
131
+ this.context,
132
+ items,
133
+ payload
134
+ );
135
+ return success(paginated);
136
+ }
137
+ }
138
+ __decorateClass([
139
+ Reactionary({
140
+ inputSchema: CategoryQueryByIdSchema,
141
+ outputSchema: CategorySchema
142
+ })
143
+ ], HclCategoryCapability.prototype, "getById", 1);
144
+ __decorateClass([
145
+ Reactionary({
146
+ inputSchema: CategoryQueryBySlugSchema,
147
+ outputSchema: CategorySchema
148
+ })
149
+ ], HclCategoryCapability.prototype, "getBySlug", 1);
150
+ __decorateClass([
151
+ Reactionary({
152
+ inputSchema: CategoryQueryForBreadcrumbSchema,
153
+ outputSchema: z.array(CategorySchema)
154
+ })
155
+ ], HclCategoryCapability.prototype, "getBreadcrumbPathToCategory", 1);
156
+ __decorateClass([
157
+ Reactionary({
158
+ inputSchema: CategoryQueryForChildCategoriesSchema,
159
+ outputSchema: CategoryPaginatedResultSchema
160
+ })
161
+ ], HclCategoryCapability.prototype, "findChildCategories", 1);
162
+ __decorateClass([
163
+ Reactionary({
164
+ inputSchema: CategoryQueryForTopCategoriesSchema,
165
+ outputSchema: CategoryPaginatedResultSchema
166
+ })
167
+ ], HclCategoryCapability.prototype, "findTopCategories", 1);
168
+ export {
169
+ HclCategoryCapability
170
+ };
@@ -0,0 +1,89 @@
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 {
13
+ FacetValueIdentifierSchema,
14
+ ProductSearchCapability,
15
+ ProductSearchQueryByTermSchema,
16
+ ProductSearchQueryCreateNavigationFilterSchema,
17
+ ProductSearchResultSchema,
18
+ Reactionary,
19
+ success
20
+ } from "@reactionary/core";
21
+ import { getLocaleParams } from "../core/locale-params.js";
22
+ class HclProductSearchCapability extends ProductSearchCapability {
23
+ constructor(cache, context, config, client, factory) {
24
+ super(cache, context);
25
+ this.config = config;
26
+ this.client = client;
27
+ this.factory = factory;
28
+ }
29
+ queryByTermPayload(payload) {
30
+ const { term, paginationOptions, categoryFilter, facets } = payload.search;
31
+ const { pageNumber, pageSize } = paginationOptions;
32
+ const { langId, currency } = getLocaleParams(this.config, this.context);
33
+ const categoryId = categoryFilter?.key || void 0;
34
+ return {
35
+ searchTerm: term || void 0,
36
+ categoryId,
37
+ limit: pageSize,
38
+ offset: (pageNumber - 1) * pageSize,
39
+ profileName: categoryId ? this.config.profiles.categoryBrowse : this.config.profiles.productSearch,
40
+ facets: facets.length > 0 ? facets.map((f) => f.key) : void 0,
41
+ langId,
42
+ currency
43
+ };
44
+ }
45
+ async queryByTerm(payload) {
46
+ const response = await this.client.findProducts(
47
+ this.queryByTermPayload(payload)
48
+ );
49
+ const value = this.factory.parseSearchResult(
50
+ this.context,
51
+ response,
52
+ payload
53
+ );
54
+ return success(value);
55
+ }
56
+ async createCategoryNavigationFilter(payload) {
57
+ const leaf = payload.categoryPath.at(-1);
58
+ const externalKey = leaf?.identifier.key ?? "";
59
+ let uniqueId = leaf?.uniqueId;
60
+ if (!uniqueId) {
61
+ const { langId } = getLocaleParams(this.config, this.context);
62
+ const catResp = await this.client.findCategories({
63
+ identifier: [externalKey],
64
+ langId
65
+ });
66
+ uniqueId = catResp.contents?.[0]?.uniqueID ?? externalKey;
67
+ }
68
+ const filter = {
69
+ facet: { key: "categories" },
70
+ key: uniqueId
71
+ };
72
+ return success(filter);
73
+ }
74
+ }
75
+ __decorateClass([
76
+ Reactionary({
77
+ inputSchema: ProductSearchQueryByTermSchema,
78
+ outputSchema: ProductSearchResultSchema
79
+ })
80
+ ], HclProductSearchCapability.prototype, "queryByTerm", 1);
81
+ __decorateClass([
82
+ Reactionary({
83
+ inputSchema: ProductSearchQueryCreateNavigationFilterSchema,
84
+ outputSchema: FacetValueIdentifierSchema
85
+ })
86
+ ], HclProductSearchCapability.prototype, "createCategoryNavigationFilter", 1);
87
+ export {
88
+ HclProductSearchCapability
89
+ };
@@ -0,0 +1,157 @@
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 {
13
+ ProductCapability,
14
+ ProductQueryByIdSchema,
15
+ ProductQueryBySKUSchema,
16
+ ProductQueryBySlugSchema,
17
+ ProductSchema,
18
+ Reactionary,
19
+ error,
20
+ success
21
+ } from "@reactionary/core";
22
+ import { getLocaleParams } from "../core/locale-params.js";
23
+ class HclProductCapability extends ProductCapability {
24
+ constructor(cache, context, config, client, factory) {
25
+ super(cache, context);
26
+ this.config = config;
27
+ this.client = client;
28
+ this.factory = factory;
29
+ }
30
+ async getById(payload) {
31
+ const { langId, currency } = getLocaleParams(this.config, this.context);
32
+ const response = await this.client.findProducts({
33
+ partNumber: [payload.identifier.key],
34
+ profileName: this.config.profiles.product,
35
+ langId,
36
+ currency
37
+ });
38
+ const products = response.contents ?? response.catalogEntryView ?? [];
39
+ const data = products[0];
40
+ if (!data) {
41
+ return error({
42
+ type: "NotFound",
43
+ identifier: payload.identifier
44
+ });
45
+ }
46
+ const value = this.factory.parseProduct(
47
+ this.context,
48
+ await this.withResolvedParentCategories(data, langId)
49
+ );
50
+ return success(value);
51
+ }
52
+ async getBySlug(payload) {
53
+ const { langId, currency } = getLocaleParams(this.config, this.context);
54
+ const token = await this.client.resolveSlug(payload.slug, langId);
55
+ if (!token || token.tokenName !== "ProductToken" || !token.tokenExternalValue) {
56
+ return error({
57
+ type: "NotFound",
58
+ identifier: payload.slug
59
+ });
60
+ }
61
+ const response = await this.client.findProducts({
62
+ partNumber: [token.tokenExternalValue],
63
+ profileName: this.config.profiles.product,
64
+ langId,
65
+ currency
66
+ });
67
+ const products = response.contents ?? response.catalogEntryView ?? [];
68
+ const data = products[0];
69
+ if (!data) {
70
+ return error({
71
+ type: "NotFound",
72
+ identifier: payload.slug
73
+ });
74
+ }
75
+ const value = this.factory.parseProduct(
76
+ this.context,
77
+ await this.withResolvedParentCategories(data, langId)
78
+ );
79
+ return success(value);
80
+ }
81
+ async getBySKU(payload) {
82
+ const { langId, currency } = getLocaleParams(this.config, this.context);
83
+ const response = await this.client.findProducts({
84
+ partNumber: [payload.variant.sku],
85
+ profileName: this.config.profiles.product,
86
+ langId,
87
+ currency
88
+ });
89
+ const products = response.contents ?? response.catalogEntryView ?? [];
90
+ const data = products[0];
91
+ if (!data) {
92
+ return error({
93
+ type: "NotFound",
94
+ identifier: payload.variant
95
+ });
96
+ }
97
+ const value = this.factory.parseProduct(
98
+ this.context,
99
+ await this.withResolvedParentCategories(data, langId)
100
+ );
101
+ return success(value);
102
+ }
103
+ /**
104
+ * Resolves `parentCatalogGroupID` path strings (e.g. "/10505/10507") to external
105
+ * category identifiers (e.g. "LivingRoomFurniture") so the factory receives
106
+ * human-readable keys rather than internal uniqueIDs.
107
+ */
108
+ async withResolvedParentCategories(data, langId) {
109
+ const rawIds = Array.isArray(data.parentCatalogGroupID) ? data.parentCatalogGroupID : data.parentCatalogGroupID ? [data.parentCatalogGroupID] : [];
110
+ const uniqueIds = [
111
+ ...new Set(
112
+ rawIds.map((p) => p.split("/").filter(Boolean).at(-1)).filter((id) => id !== void 0)
113
+ )
114
+ ];
115
+ if (uniqueIds.length === 0)
116
+ return data;
117
+ const catResp = await this.client.findCategories({ id: uniqueIds, langId });
118
+ const idToIdentifier = new Map(
119
+ (catResp.contents ?? []).map((c) => [c.uniqueID, c.identifier])
120
+ );
121
+ const resolvedIds = uniqueIds.map((id) => idToIdentifier.get(id) ?? id);
122
+ return { ...data, parentCatalogGroupID: resolvedIds };
123
+ }
124
+ }
125
+ __decorateClass([
126
+ Reactionary({
127
+ inputSchema: ProductQueryByIdSchema,
128
+ outputSchema: ProductSchema,
129
+ cache: true,
130
+ cacheTimeToLiveInSeconds: 300,
131
+ currencyDependentCaching: false,
132
+ localeDependentCaching: false
133
+ })
134
+ ], HclProductCapability.prototype, "getById", 1);
135
+ __decorateClass([
136
+ Reactionary({
137
+ inputSchema: ProductQueryBySlugSchema,
138
+ outputSchema: ProductSchema,
139
+ cache: true,
140
+ cacheTimeToLiveInSeconds: 300,
141
+ currencyDependentCaching: false,
142
+ localeDependentCaching: false
143
+ })
144
+ ], HclProductCapability.prototype, "getBySlug", 1);
145
+ __decorateClass([
146
+ Reactionary({
147
+ inputSchema: ProductQueryBySKUSchema,
148
+ outputSchema: ProductSchema,
149
+ cache: true,
150
+ cacheTimeToLiveInSeconds: 300,
151
+ currencyDependentCaching: false,
152
+ localeDependentCaching: false
153
+ })
154
+ ], HclProductCapability.prototype, "getBySKU", 1);
155
+ export {
156
+ HclProductCapability
157
+ };
package/core/client.js ADDED
@@ -0,0 +1,120 @@
1
+ class HclClient {
2
+ constructor(config) {
3
+ this.config = config;
4
+ const origin = config.apiUrl.replace(/\/+$/, "");
5
+ const apiPath = "/search/resources/api/v2";
6
+ this.baseUrl = `${origin}${apiPath}`;
7
+ }
8
+ baseUrl;
9
+ async findProducts(query) {
10
+ const params = new URLSearchParams();
11
+ params.set("storeId", query.storeId ?? this.config.storeId);
12
+ const catalogId = query.catalogId ?? this.config.catalogId;
13
+ if (catalogId)
14
+ params.set("catalogId", catalogId);
15
+ if (query.langId)
16
+ params.set("langId", query.langId);
17
+ if (query.currency)
18
+ params.set("currency", query.currency);
19
+ if (query.categoryId)
20
+ params.set("categoryId", query.categoryId);
21
+ if (query.searchTerm)
22
+ params.set("searchTerm", query.searchTerm);
23
+ if (query.contractId)
24
+ params.set("contractId", query.contractId);
25
+ if (query.profileName)
26
+ params.set("profileName", query.profileName);
27
+ if (query.limit !== void 0)
28
+ params.set("limit", String(query.limit));
29
+ if (query.offset !== void 0)
30
+ params.set("offset", String(query.offset));
31
+ if (query.checkEntitlement !== void 0) {
32
+ params.set("checkEntitlement", String(query.checkEntitlement));
33
+ }
34
+ for (const id of query.id ?? []) {
35
+ params.append("id", id);
36
+ }
37
+ for (const partNumber of query.partNumber ?? []) {
38
+ params.append("partNumber", partNumber);
39
+ }
40
+ for (const facet of query.facets ?? []) {
41
+ params.append("facet", facet);
42
+ }
43
+ const url = `${this.baseUrl}/products?${params.toString()}`;
44
+ const response = await fetch(url, {
45
+ method: "GET",
46
+ headers: { Accept: "application/json" }
47
+ });
48
+ if (!response.ok) {
49
+ throw new Error(
50
+ `HCL API error ${response.status} ${response.statusText} for URL: ${url}`
51
+ );
52
+ }
53
+ return response.json();
54
+ }
55
+ /**
56
+ * Resolve a URL slug to an HCL token (product partNumber, category ID, etc.).
57
+ * Calls GET /api/v2/urls?storeId=X&identifier=<slug>
58
+ * Returns undefined when the slug is not found (404).
59
+ */
60
+ async resolveSlug(slug, langId) {
61
+ const params = new URLSearchParams();
62
+ params.set("storeId", this.config.storeId);
63
+ params.append("identifier", slug);
64
+ if (langId)
65
+ params.set("langId", langId);
66
+ const url = `${this.baseUrl}/urls?${params.toString()}`;
67
+ const response = await fetch(url, {
68
+ method: "GET",
69
+ headers: { Accept: "application/json" }
70
+ });
71
+ if (response.status === 404)
72
+ return void 0;
73
+ if (!response.ok) {
74
+ throw new Error(
75
+ `HCL URL resolve error ${response.status} ${response.statusText} for URL: ${url}`
76
+ );
77
+ }
78
+ const data = await response.json();
79
+ return data.contents?.[0];
80
+ }
81
+ /**
82
+ * Query categories from the HCL Commerce Query Service.
83
+ * Calls GET /api/v2/categories with the given query parameters.
84
+ */
85
+ async findCategories(query) {
86
+ const params = new URLSearchParams();
87
+ params.set("storeId", query.storeId ?? this.config.storeId);
88
+ const catalogId = query.catalogId ?? this.config.catalogId;
89
+ if (catalogId)
90
+ params.set("catalogId", catalogId);
91
+ if (query.langId)
92
+ params.set("langId", query.langId);
93
+ if (query.parentCategoryId)
94
+ params.set("parentCategoryId", query.parentCategoryId);
95
+ if (query.depthAndLimit)
96
+ params.set("depthAndLimit", query.depthAndLimit);
97
+ if (query.profileName)
98
+ params.set("profileName", query.profileName);
99
+ for (const id of query.id ?? []) {
100
+ params.append("id", id);
101
+ }
102
+ for (const identifier of query.identifier ?? []) {
103
+ params.append("identifier", identifier);
104
+ }
105
+ const url = `${this.baseUrl}/categories?${params.toString()}`;
106
+ const response = await fetch(url, {
107
+ method: "GET",
108
+ headers: { Accept: "application/json" }
109
+ });
110
+ if (!response.ok) {
111
+ throw new Error(
112
+ `HCL API error ${response.status} ${response.statusText} for URL: ${url}`
113
+ );
114
+ }
115
+ return response.json();
116
+ }
117
+ }
118
+ export {
119
+ HclClient
120
+ };
@@ -0,0 +1,97 @@
1
+ import {
2
+ CategoryPaginatedResultSchema,
3
+ ProductSchema
4
+ } from "@reactionary/core";
5
+ import { HclCategorySchema } from "../schema/category.schema.js";
6
+ import {
7
+ HclCapabilitiesSchema
8
+ } from "../schema/capabilities.schema.js";
9
+ import {
10
+ HclConfigurationSchema
11
+ } from "../schema/configuration.schema.js";
12
+ import {
13
+ resolveCapabilityWithFactory
14
+ } from "./initialize.types.js";
15
+ import { HclClient } from "./client.js";
16
+ import {
17
+ HclCategoryFactory,
18
+ HclProductFactory,
19
+ HclProductSearchFactory
20
+ } from "../factories/index.js";
21
+ import { HclProductCapability } from "../capabilities/product.capability.js";
22
+ import { HclCategoryCapability } from "../capabilities/category.capability.js";
23
+ import { HclProductSearchCapability } from "../capabilities/product-search.capability.js";
24
+ import { ProductSearchResultSchema } from "@reactionary/core";
25
+ function withHclCapabilities(configuration, capabilities) {
26
+ return (cache, context) => {
27
+ const client = {};
28
+ const config = HclConfigurationSchema.parse(configuration);
29
+ const caps = HclCapabilitiesSchema.parse(capabilities);
30
+ const hclClient = new HclClient(config);
31
+ const buildCapabilityArgs = (factory) => ({
32
+ cache,
33
+ context,
34
+ config,
35
+ hclClient,
36
+ factory
37
+ });
38
+ if (caps.product?.enabled) {
39
+ client.product = resolveCapabilityWithFactory(
40
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
41
+ capabilities.product,
42
+ {
43
+ factory: new HclProductFactory(ProductSchema),
44
+ capability: (args) => new HclProductCapability(
45
+ args.cache,
46
+ args.context,
47
+ args.config,
48
+ args.hclClient,
49
+ args.factory
50
+ )
51
+ },
52
+ buildCapabilityArgs
53
+ );
54
+ }
55
+ if (caps.category?.enabled) {
56
+ client.category = resolveCapabilityWithFactory(
57
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
58
+ capabilities.category,
59
+ {
60
+ factory: new HclCategoryFactory(
61
+ HclCategorySchema,
62
+ CategoryPaginatedResultSchema
63
+ ),
64
+ capability: (args) => new HclCategoryCapability(
65
+ args.cache,
66
+ args.context,
67
+ args.config,
68
+ args.hclClient,
69
+ args.factory
70
+ )
71
+ },
72
+ buildCapabilityArgs
73
+ );
74
+ }
75
+ if (caps.productSearch?.enabled) {
76
+ client.productSearch = resolveCapabilityWithFactory(
77
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
78
+ capabilities.productSearch,
79
+ {
80
+ factory: new HclProductSearchFactory(ProductSearchResultSchema),
81
+ capability: (args) => new HclProductSearchCapability(
82
+ args.cache,
83
+ args.context,
84
+ args.config,
85
+ args.hclClient,
86
+ args.factory
87
+ )
88
+ },
89
+ buildCapabilityArgs
90
+ );
91
+ }
92
+ return client;
93
+ };
94
+ }
95
+ export {
96
+ withHclCapabilities
97
+ };
@@ -0,0 +1,8 @@
1
+ function resolveCapabilityWithFactory(capability, defaults, buildCapabilityArgs) {
2
+ const factory = capability?.factory ?? defaults.factory;
3
+ const capabilityFactory = capability?.capability ?? defaults.capability;
4
+ return capabilityFactory(buildCapabilityArgs(factory));
5
+ }
6
+ export {
7
+ resolveCapabilityWithFactory
8
+ };
@@ -0,0 +1,9 @@
1
+ function getLocaleParams(config, context) {
2
+ return {
3
+ langId: config.localeMap[context.languageContext.locale],
4
+ currency: context.languageContext.currencyCode
5
+ };
6
+ }
7
+ export {
8
+ getLocaleParams
9
+ };