@reactionary/provider-commercetools 0.3.15 → 0.3.17
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/core/client.js +83 -9
- package/core/initialize.js +10 -1
- package/core/token-cache.js +5 -6
- package/package.json +2 -2
- package/providers/index.js +1 -0
- package/providers/inventory.provider.js +5 -2
- package/providers/price.provider.js +18 -16
- package/providers/product-list.provider.js +389 -0
- package/schema/capabilities.schema.js +1 -0
- package/schema/configuration.schema.js +5 -1
- package/src/core/client.d.ts +17 -1
- package/src/core/token-cache.d.ts +2 -2
- package/src/providers/index.d.ts +1 -0
- package/src/providers/price.provider.d.ts +0 -4
- package/src/providers/product-list.provider.d.ts +27 -0
- package/src/schema/capabilities.schema.d.ts +1 -0
- package/src/schema/configuration.schema.d.ts +4 -0
- package/src/schema/session.schema.d.ts +1 -0
package/core/client.js
CHANGED
|
@@ -10,12 +10,14 @@ import {
|
|
|
10
10
|
import * as crypto from "crypto";
|
|
11
11
|
import createDebug from "debug";
|
|
12
12
|
import { RequestContextTokenCache } from "./token-cache.js";
|
|
13
|
+
import { CommercetoolsSessionSchema } from "../schema/session.schema.js";
|
|
13
14
|
const debug = createDebug("reactionary:commercetools");
|
|
15
|
+
const PROVIDER_SESSION_KEY = "COMMERCETOOLS_PROVIDER";
|
|
14
16
|
class CommercetoolsAPI {
|
|
15
17
|
constructor(config, context) {
|
|
16
18
|
this.config = config;
|
|
17
19
|
this.context = context;
|
|
18
|
-
this.
|
|
20
|
+
this.tokenCache = new RequestContextTokenCache(this.context, PROVIDER_SESSION_KEY);
|
|
19
21
|
}
|
|
20
22
|
async getClient() {
|
|
21
23
|
if (!this.client) {
|
|
@@ -29,6 +31,77 @@ class CommercetoolsAPI {
|
|
|
29
31
|
}
|
|
30
32
|
return this.adminClient;
|
|
31
33
|
}
|
|
34
|
+
getSessionData() {
|
|
35
|
+
return this.context.session[PROVIDER_SESSION_KEY] ? this.context.session[PROVIDER_SESSION_KEY] : CommercetoolsSessionSchema.parse({});
|
|
36
|
+
}
|
|
37
|
+
setSessionData(sessionData) {
|
|
38
|
+
const existingData = this.context.session[PROVIDER_SESSION_KEY];
|
|
39
|
+
this.context.session[PROVIDER_SESSION_KEY] = {
|
|
40
|
+
...existingData,
|
|
41
|
+
...sessionData
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Only caches it pr session for now...... but still better than every call
|
|
46
|
+
* @param key
|
|
47
|
+
* @returns
|
|
48
|
+
*/
|
|
49
|
+
async resolveChannelIdByKey(key) {
|
|
50
|
+
const sessionData = this.getSessionData();
|
|
51
|
+
const cacheKey = `___channel_${key}`;
|
|
52
|
+
const cachedValue = sessionData[cacheKey];
|
|
53
|
+
if (cachedValue) {
|
|
54
|
+
if (debug.enabled) {
|
|
55
|
+
debug(`Resolved channel ${key} from cache`);
|
|
56
|
+
}
|
|
57
|
+
return cachedValue + "";
|
|
58
|
+
}
|
|
59
|
+
const client = await this.getAdminClient();
|
|
60
|
+
const response = await client.withProjectKey({ projectKey: this.config.projectKey }).channels().withKey({ key }).get().execute();
|
|
61
|
+
const channel = response.body;
|
|
62
|
+
this.setSessionData({
|
|
63
|
+
cacheKey: channel.id
|
|
64
|
+
});
|
|
65
|
+
if (debug.enabled) {
|
|
66
|
+
debug(`Resolved channel ${key} from API and cached it`);
|
|
67
|
+
}
|
|
68
|
+
return channel.id;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Only caches it pr session for now...... but still better than every call
|
|
72
|
+
* @param key
|
|
73
|
+
* @returns
|
|
74
|
+
*/
|
|
75
|
+
async resolveChannelIdByRole(role) {
|
|
76
|
+
const sessionData = this.getSessionData();
|
|
77
|
+
const cacheKey = `___channel_role_${role}`;
|
|
78
|
+
const cachedValue = sessionData[cacheKey];
|
|
79
|
+
if (cachedValue) {
|
|
80
|
+
if (debug.enabled) {
|
|
81
|
+
debug(`Resolved channel ${role} from cache`);
|
|
82
|
+
}
|
|
83
|
+
return cachedValue + "";
|
|
84
|
+
}
|
|
85
|
+
const client = await this.getAdminClient();
|
|
86
|
+
const response = await client.withProjectKey({ projectKey: this.config.projectKey }).channels().get({
|
|
87
|
+
queryArgs: {
|
|
88
|
+
where: `roles contains any (:role)`,
|
|
89
|
+
"var.role": role
|
|
90
|
+
}
|
|
91
|
+
}).execute();
|
|
92
|
+
const channels = response.body;
|
|
93
|
+
if (channels.results.length === 0) {
|
|
94
|
+
throw new Error(`No channel found with role ${role}`);
|
|
95
|
+
}
|
|
96
|
+
const channel = channels.results[0];
|
|
97
|
+
this.setSessionData({
|
|
98
|
+
[cacheKey]: channel.id
|
|
99
|
+
});
|
|
100
|
+
if (debug.enabled) {
|
|
101
|
+
debug(`Resolved channel ${role} from API and cached it`);
|
|
102
|
+
}
|
|
103
|
+
return channel.id;
|
|
104
|
+
}
|
|
32
105
|
async createAdminClient() {
|
|
33
106
|
let builder = this.createBaseClientBuilder();
|
|
34
107
|
builder = builder.withAnonymousSessionFlow({
|
|
@@ -42,11 +115,11 @@ class CommercetoolsAPI {
|
|
|
42
115
|
return createApiBuilderFromCtpClient(builder.build());
|
|
43
116
|
}
|
|
44
117
|
async createClient() {
|
|
45
|
-
let session = await this.
|
|
118
|
+
let session = await this.tokenCache.get();
|
|
46
119
|
const isNewSession = !session || !session.refreshToken;
|
|
47
120
|
if (isNewSession) {
|
|
48
121
|
await this.becomeGuest();
|
|
49
|
-
session = await this.
|
|
122
|
+
session = await this.tokenCache.get();
|
|
50
123
|
}
|
|
51
124
|
let builder = this.createBaseClientBuilder();
|
|
52
125
|
builder = builder.withRefreshTokenFlow({
|
|
@@ -57,7 +130,7 @@ class CommercetoolsAPI {
|
|
|
57
130
|
host: this.config.authUrl,
|
|
58
131
|
projectKey: this.config.projectKey,
|
|
59
132
|
refreshToken: session?.refreshToken || "",
|
|
60
|
-
tokenCache: this.
|
|
133
|
+
tokenCache: this.tokenCache
|
|
61
134
|
});
|
|
62
135
|
return createApiBuilderFromCtpClient(builder.build());
|
|
63
136
|
}
|
|
@@ -92,7 +165,7 @@ class CommercetoolsAPI {
|
|
|
92
165
|
clientSecret: this.config.clientSecret,
|
|
93
166
|
user: { username, password }
|
|
94
167
|
},
|
|
95
|
-
tokenCache: this.
|
|
168
|
+
tokenCache: this.tokenCache,
|
|
96
169
|
scopes: this.config.scopes
|
|
97
170
|
});
|
|
98
171
|
const loginClient = createApiBuilderFromCtpClient(loginBuilder.build());
|
|
@@ -111,7 +184,7 @@ class CommercetoolsAPI {
|
|
|
111
184
|
});
|
|
112
185
|
}
|
|
113
186
|
async logout() {
|
|
114
|
-
await this.
|
|
187
|
+
await this.tokenCache.set({ token: "", refreshToken: "", expirationTime: 0 });
|
|
115
188
|
const identity = {
|
|
116
189
|
type: "Anonymous"
|
|
117
190
|
};
|
|
@@ -119,7 +192,7 @@ class CommercetoolsAPI {
|
|
|
119
192
|
}
|
|
120
193
|
// FIXME: This can fail if the short-lived access token has expired. In other words, probably missing a token refresh.
|
|
121
194
|
async introspect() {
|
|
122
|
-
const session = await this.
|
|
195
|
+
const session = await this.tokenCache.get();
|
|
123
196
|
if (!session || !session.token) {
|
|
124
197
|
const identity = {
|
|
125
198
|
type: "Anonymous"
|
|
@@ -191,7 +264,7 @@ class CommercetoolsAPI {
|
|
|
191
264
|
}
|
|
192
265
|
);
|
|
193
266
|
const result = await response.json();
|
|
194
|
-
this.
|
|
267
|
+
this.tokenCache.set({
|
|
195
268
|
expirationTime: Date.now() + Number(result.expires_in) * 1e3 - 5 * 60 * 1e3,
|
|
196
269
|
token: result.access_token,
|
|
197
270
|
refreshToken: result.refresh_token
|
|
@@ -235,5 +308,6 @@ class CommercetoolsAPI {
|
|
|
235
308
|
}
|
|
236
309
|
}
|
|
237
310
|
export {
|
|
238
|
-
CommercetoolsAPI
|
|
311
|
+
CommercetoolsAPI,
|
|
312
|
+
PROVIDER_SESSION_KEY
|
|
239
313
|
};
|
package/core/initialize.js
CHANGED
|
@@ -18,7 +18,8 @@ import {
|
|
|
18
18
|
CommercetoolsProfileProvider,
|
|
19
19
|
CommercetoolsStoreProvider,
|
|
20
20
|
CommercetoolsProductReviewsProvider,
|
|
21
|
-
CommercetoolsProductAssociationsProvider
|
|
21
|
+
CommercetoolsProductAssociationsProvider,
|
|
22
|
+
CommercetoolsProductListProvider
|
|
22
23
|
} from "../providers/index.js";
|
|
23
24
|
import { CommercetoolsAPI } from "./client.js";
|
|
24
25
|
function withCommercetoolsCapabilities(configuration, capabilities) {
|
|
@@ -59,6 +60,14 @@ function withCommercetoolsCapabilities(configuration, capabilities) {
|
|
|
59
60
|
commercetoolsApi
|
|
60
61
|
);
|
|
61
62
|
}
|
|
63
|
+
if (caps.productList) {
|
|
64
|
+
client.productList = new CommercetoolsProductListProvider(
|
|
65
|
+
config,
|
|
66
|
+
cache,
|
|
67
|
+
context,
|
|
68
|
+
commercetoolsApi
|
|
69
|
+
);
|
|
70
|
+
}
|
|
62
71
|
if (caps.productReviews) {
|
|
63
72
|
client.productReviews = new CommercetoolsProductReviewsProvider(
|
|
64
73
|
config,
|
package/core/token-cache.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { CommercetoolsSessionSchema } from "../schema/session.schema.js";
|
|
2
|
-
const PROVIDER_COMMERCETOOLS_SESSION_KEY = "PROVIDER_COMMERCETOOLS";
|
|
3
2
|
class RequestContextTokenCache {
|
|
4
|
-
constructor(context) {
|
|
3
|
+
constructor(context, sessionProviderKey) {
|
|
5
4
|
this.context = context;
|
|
5
|
+
this.sessionProviderKey = sessionProviderKey;
|
|
6
6
|
}
|
|
7
7
|
async get(tokenCacheOptions) {
|
|
8
8
|
const session = CommercetoolsSessionSchema.parse(
|
|
9
|
-
this.context.session[
|
|
9
|
+
this.context.session[this.sessionProviderKey] || {}
|
|
10
10
|
);
|
|
11
11
|
if (!session) {
|
|
12
12
|
return {
|
|
@@ -23,15 +23,14 @@ class RequestContextTokenCache {
|
|
|
23
23
|
}
|
|
24
24
|
async set(cache, tokenCacheOptions) {
|
|
25
25
|
const session = CommercetoolsSessionSchema.parse(
|
|
26
|
-
this.context.session[
|
|
26
|
+
this.context.session[this.sessionProviderKey] || {}
|
|
27
27
|
);
|
|
28
|
-
this.context.session[
|
|
28
|
+
this.context.session[this.sessionProviderKey] = session;
|
|
29
29
|
session.refreshToken = cache.refreshToken;
|
|
30
30
|
session.token = cache.token;
|
|
31
31
|
session.expirationTime = cache.expirationTime;
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
export {
|
|
35
|
-
PROVIDER_COMMERCETOOLS_SESSION_KEY,
|
|
36
35
|
RequestContextTokenCache
|
|
37
36
|
};
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reactionary/provider-commercetools",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.17",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"types": "src/index.d.ts",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@reactionary/core": "0.3.
|
|
7
|
+
"@reactionary/core": "0.3.17",
|
|
8
8
|
"debug": "^4.4.3",
|
|
9
9
|
"zod": "4.1.9",
|
|
10
10
|
"@commercetools/ts-client": "^4.2.1",
|
package/providers/index.js
CHANGED
|
@@ -5,6 +5,7 @@ export * from "./inventory.provider.js";
|
|
|
5
5
|
export * from "./order-search.provider.js";
|
|
6
6
|
export * from "./price.provider.js";
|
|
7
7
|
export * from "./product-associations.provider.js";
|
|
8
|
+
export * from "./product-list.provider.js";
|
|
8
9
|
export * from "./product.provider.js";
|
|
9
10
|
export * from "./product-reviews.provider.js";
|
|
10
11
|
export * from "./profile.provider.js";
|
|
@@ -23,8 +23,7 @@ class CommercetoolsInventoryProvider extends InventoryProvider {
|
|
|
23
23
|
async getBySKU(payload) {
|
|
24
24
|
const client = await this.getClient();
|
|
25
25
|
try {
|
|
26
|
-
const
|
|
27
|
-
const channelId = channel.body.id;
|
|
26
|
+
const channelId = await this.commercetools.resolveChannelIdByKey(payload.fulfilmentCenter.key);
|
|
28
27
|
const remote = await client.inventory().get({
|
|
29
28
|
queryArgs: {
|
|
30
29
|
where: "sku=:sku AND supplyChannel(id=:channel)",
|
|
@@ -66,6 +65,10 @@ class CommercetoolsInventoryProvider extends InventoryProvider {
|
|
|
66
65
|
}
|
|
67
66
|
__decorateClass([
|
|
68
67
|
Reactionary({
|
|
68
|
+
cache: true,
|
|
69
|
+
cacheTimeToLiveInSeconds: 300,
|
|
70
|
+
currencyDependentCaching: false,
|
|
71
|
+
localeDependentCaching: false,
|
|
69
72
|
inputSchema: InventoryQueryBySKUSchema,
|
|
70
73
|
outputSchema: InventorySchema
|
|
71
74
|
})
|
|
@@ -25,7 +25,12 @@ class CommercetoolsPriceProvider extends PriceProvider {
|
|
|
25
25
|
}
|
|
26
26
|
async getCustomerPrice(payload) {
|
|
27
27
|
const client = await this.getClient();
|
|
28
|
-
|
|
28
|
+
let priceChannelId;
|
|
29
|
+
if (this.config.customerPriceChannelKey) {
|
|
30
|
+
priceChannelId = await this.commercetools.resolveChannelIdByKey(this.config.customerPriceChannelKey);
|
|
31
|
+
} else {
|
|
32
|
+
priceChannelId = await this.commercetools.resolveChannelIdByRole("Primary");
|
|
33
|
+
}
|
|
29
34
|
const response = await client.productProjections().get({
|
|
30
35
|
queryArgs: {
|
|
31
36
|
staged: false,
|
|
@@ -46,7 +51,12 @@ class CommercetoolsPriceProvider extends PriceProvider {
|
|
|
46
51
|
}
|
|
47
52
|
async getListPrice(payload) {
|
|
48
53
|
const client = await this.getClient();
|
|
49
|
-
|
|
54
|
+
let priceChannelId;
|
|
55
|
+
if (this.config.listPriceChannelKey) {
|
|
56
|
+
priceChannelId = await this.commercetools.resolveChannelIdByKey(this.config.listPriceChannelKey);
|
|
57
|
+
} else {
|
|
58
|
+
priceChannelId = await this.commercetools.resolveChannelIdByRole("Primary");
|
|
59
|
+
}
|
|
50
60
|
const response = await client.productProjections().get({
|
|
51
61
|
queryArgs: {
|
|
52
62
|
staged: false,
|
|
@@ -79,8 +89,12 @@ class CommercetoolsPriceProvider extends PriceProvider {
|
|
|
79
89
|
value: price.value.centAmount / 100,
|
|
80
90
|
currency: price.value.currencyCode
|
|
81
91
|
};
|
|
92
|
+
let isOnSale = false;
|
|
82
93
|
if (options.includeDiscounts) {
|
|
83
94
|
const discountedPrice = price.discounted?.value || price.value;
|
|
95
|
+
if (price.discounted) {
|
|
96
|
+
isOnSale = true;
|
|
97
|
+
}
|
|
84
98
|
unitPrice = {
|
|
85
99
|
value: discountedPrice.centAmount / 100,
|
|
86
100
|
currency: price.value.currencyCode
|
|
@@ -94,23 +108,11 @@ class CommercetoolsPriceProvider extends PriceProvider {
|
|
|
94
108
|
const result = {
|
|
95
109
|
identifier,
|
|
96
110
|
tieredPrices: [],
|
|
97
|
-
unitPrice
|
|
111
|
+
unitPrice,
|
|
112
|
+
onSale: isOnSale
|
|
98
113
|
};
|
|
99
114
|
return result;
|
|
100
115
|
}
|
|
101
|
-
async getChannels() {
|
|
102
|
-
const adminClient = await this.commercetools.getAdminClient();
|
|
103
|
-
const offerPriceChannelPromise = adminClient.withProjectKey({ projectKey: this.config.projectKey }).channels().withKey({ key: "Offer Price" }).get().execute();
|
|
104
|
-
const listPriceChannelPromise = adminClient.withProjectKey({ projectKey: this.config.projectKey }).channels().withKey({ key: "List Price" }).get().execute();
|
|
105
|
-
const [offerChannel, listChannel] = await Promise.all([
|
|
106
|
-
offerPriceChannelPromise,
|
|
107
|
-
listPriceChannelPromise
|
|
108
|
-
]);
|
|
109
|
-
return {
|
|
110
|
-
offer: offerChannel.body.id,
|
|
111
|
-
list: listChannel.body.id
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
116
|
}
|
|
115
117
|
__decorateClass([
|
|
116
118
|
Reactionary({
|
|
@@ -0,0 +1,389 @@
|
|
|
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
|
+
error,
|
|
14
|
+
ProductListItemMutationCreateSchema,
|
|
15
|
+
ProductListItemMutationDeleteSchema,
|
|
16
|
+
ProductListItemMutationUpdateSchema,
|
|
17
|
+
ProductListItemPaginatedResultsSchema,
|
|
18
|
+
ProductListItemQuerySchema,
|
|
19
|
+
ProductListItemSchema,
|
|
20
|
+
ProductListMutationCreateSchema,
|
|
21
|
+
ProductListMutationDeleteSchema,
|
|
22
|
+
ProductListMutationUpdateSchema,
|
|
23
|
+
ProductListPaginatedResultsSchema,
|
|
24
|
+
ProductListProvider,
|
|
25
|
+
ProductListQueryByIdSchema,
|
|
26
|
+
ProductListQuerySchema,
|
|
27
|
+
ProductListSchema,
|
|
28
|
+
Reactionary,
|
|
29
|
+
success
|
|
30
|
+
} from "@reactionary/core";
|
|
31
|
+
class CommercetoolsProductListProvider extends ProductListProvider {
|
|
32
|
+
constructor(config, cache, context, commercetools) {
|
|
33
|
+
super(cache, context);
|
|
34
|
+
this.config = config;
|
|
35
|
+
this.commercetools = commercetools;
|
|
36
|
+
}
|
|
37
|
+
async getClient() {
|
|
38
|
+
const client = await this.commercetools.getClient();
|
|
39
|
+
return client.withProjectKey({ projectKey: this.config.projectKey }).me();
|
|
40
|
+
}
|
|
41
|
+
async getById(payload) {
|
|
42
|
+
try {
|
|
43
|
+
const client = await this.getClient();
|
|
44
|
+
const response = await client.shoppingLists().withId({ ID: payload.identifier.key }).get().execute();
|
|
45
|
+
return success(this.parseSingle(response.body));
|
|
46
|
+
} catch (err) {
|
|
47
|
+
if (err.statusCode === 404) {
|
|
48
|
+
return error({
|
|
49
|
+
type: "NotFound",
|
|
50
|
+
identifier: payload
|
|
51
|
+
});
|
|
52
|
+
} else {
|
|
53
|
+
throw err;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async queryLists(payload) {
|
|
58
|
+
if (this.context.session.identityContext?.identity?.type !== "Registered") {
|
|
59
|
+
return success({
|
|
60
|
+
items: [],
|
|
61
|
+
pageNumber: 1,
|
|
62
|
+
pageSize: payload.search.paginationOptions.pageSize,
|
|
63
|
+
totalCount: 0,
|
|
64
|
+
totalPages: 0,
|
|
65
|
+
identifier: payload.search
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
const client = await this.getClient();
|
|
69
|
+
const response = await client.shoppingLists().get({
|
|
70
|
+
queryArgs: {
|
|
71
|
+
where: `custom(fields(listType=:listType))`,
|
|
72
|
+
sort: "createdAt desc",
|
|
73
|
+
"var.listType": payload.search.listType,
|
|
74
|
+
limit: payload.search.paginationOptions.pageSize,
|
|
75
|
+
offset: (payload.search.paginationOptions.pageNumber - 1) * payload.search.paginationOptions.pageSize
|
|
76
|
+
}
|
|
77
|
+
}).execute();
|
|
78
|
+
return success({
|
|
79
|
+
items: response.body.results.map((list) => this.parseSingle(list)),
|
|
80
|
+
pageNumber: payload.search.paginationOptions.pageNumber,
|
|
81
|
+
pageSize: payload.search.paginationOptions.pageSize,
|
|
82
|
+
totalCount: response.body.total || 0,
|
|
83
|
+
totalPages: Math.ceil((response.body.total || 0) / payload.search.paginationOptions.pageSize),
|
|
84
|
+
identifier: payload.search
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
async addList(mutation) {
|
|
88
|
+
const client = await this.getClient();
|
|
89
|
+
const localeString = this.getLocaleString();
|
|
90
|
+
if (this.context.session.identityContext?.identity?.type !== "Registered") {
|
|
91
|
+
return error({
|
|
92
|
+
type: "InvalidInput",
|
|
93
|
+
error: "Only registered users can have product lists"
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
const draft = {
|
|
97
|
+
name: { [localeString]: mutation.list.name },
|
|
98
|
+
description: mutation.list.description ? { [localeString]: mutation.list.description } : void 0,
|
|
99
|
+
custom: {
|
|
100
|
+
type: {
|
|
101
|
+
key: "reactionaryShoppingList",
|
|
102
|
+
typeId: "type"
|
|
103
|
+
},
|
|
104
|
+
fields: {
|
|
105
|
+
listType: mutation.list.type,
|
|
106
|
+
imageUrl: mutation.list.image ? mutation.list.image.sourceUrl : void 0,
|
|
107
|
+
publishedDate: mutation.list.publishDate ? new Date(mutation.list.publishDate) : void 0,
|
|
108
|
+
published: mutation.list.published || true
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
const response = await client.shoppingLists().post({
|
|
113
|
+
body: draft
|
|
114
|
+
}).execute();
|
|
115
|
+
return success(this.parseSingle(response.body));
|
|
116
|
+
}
|
|
117
|
+
async updateList(mutation) {
|
|
118
|
+
const client = await this.getClient();
|
|
119
|
+
const actions = [];
|
|
120
|
+
const localeString = this.getLocaleString();
|
|
121
|
+
if (mutation.name) {
|
|
122
|
+
actions.push({
|
|
123
|
+
action: "changeName",
|
|
124
|
+
name: { [localeString]: mutation.name }
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
if (mutation.description !== void 0) {
|
|
128
|
+
actions.push({
|
|
129
|
+
action: "setDescription",
|
|
130
|
+
description: mutation.description ? { [localeString]: mutation.description } : void 0
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
if (mutation.published) {
|
|
134
|
+
actions.push({
|
|
135
|
+
action: "setCustomField",
|
|
136
|
+
name: "published",
|
|
137
|
+
value: mutation.published
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
if (mutation.publishDate) {
|
|
141
|
+
actions.push({
|
|
142
|
+
action: "setCustomField",
|
|
143
|
+
name: "publishedDate",
|
|
144
|
+
value: new Date(mutation.publishDate)
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
if (mutation.image) {
|
|
148
|
+
actions.push({
|
|
149
|
+
action: "setCustomField",
|
|
150
|
+
name: "imageUrl",
|
|
151
|
+
value: mutation.image.sourceUrl
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
const update = {
|
|
155
|
+
version: 0,
|
|
156
|
+
// The auto-correcting middleware will deal with the version
|
|
157
|
+
actions
|
|
158
|
+
};
|
|
159
|
+
const response = await client.shoppingLists().withId({ ID: mutation.list.key }).post({ body: update }).execute();
|
|
160
|
+
return success(this.parseSingle(response.body));
|
|
161
|
+
}
|
|
162
|
+
async deleteList(mutation) {
|
|
163
|
+
const client = await this.getClient();
|
|
164
|
+
const newestVersion = await client.shoppingLists().withId({ ID: mutation.list.key }).get().execute().then((response) => response.body.version);
|
|
165
|
+
await client.shoppingLists().withId({ ID: mutation.list.key }).delete({
|
|
166
|
+
queryArgs: {
|
|
167
|
+
version: newestVersion
|
|
168
|
+
}
|
|
169
|
+
}).execute();
|
|
170
|
+
return success(void 0);
|
|
171
|
+
}
|
|
172
|
+
async queryListItems(query) {
|
|
173
|
+
const client = await this.getClient();
|
|
174
|
+
const response = await client.shoppingLists().withId({ ID: query.search.list.key }).get({
|
|
175
|
+
queryArgs: { expand: "lineItems[*].variant" }
|
|
176
|
+
}).execute();
|
|
177
|
+
const items = response.body.lineItems.map((lineItem) => this.parseProductListItem(query.search.list, lineItem));
|
|
178
|
+
return success({
|
|
179
|
+
items: items.slice((query.search.paginationOptions.pageNumber - 1) * query.search.paginationOptions.pageSize, query.search.paginationOptions.pageNumber * query.search.paginationOptions.pageSize),
|
|
180
|
+
identifier: query.search,
|
|
181
|
+
pageNumber: query.search.paginationOptions.pageNumber,
|
|
182
|
+
pageSize: query.search.paginationOptions.pageSize,
|
|
183
|
+
totalCount: items.length,
|
|
184
|
+
totalPages: Math.ceil(items.length / query.search.paginationOptions.pageSize)
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
async addItem(mutation) {
|
|
188
|
+
const client = await this.getClient();
|
|
189
|
+
const lineItemDraft = {
|
|
190
|
+
action: "addLineItem",
|
|
191
|
+
sku: mutation.listItem.variant.sku,
|
|
192
|
+
quantity: mutation.listItem.quantity,
|
|
193
|
+
custom: {
|
|
194
|
+
type: {
|
|
195
|
+
key: "reactionaryShoppingListItem",
|
|
196
|
+
typeId: "type"
|
|
197
|
+
},
|
|
198
|
+
fields: {
|
|
199
|
+
notes: mutation.listItem.notes || "",
|
|
200
|
+
order: mutation.listItem.order || 1
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
const update = {
|
|
205
|
+
version: 0,
|
|
206
|
+
// The auto-correcting middleware will deal with the version
|
|
207
|
+
actions: [lineItemDraft]
|
|
208
|
+
};
|
|
209
|
+
const response = await client.shoppingLists().withId({ ID: mutation.list.key }).post({ body: update, queryArgs: { expand: "lineItems[*].variant" } }).execute();
|
|
210
|
+
const lastItem = response.body.lineItems[response.body.lineItems.length - 1];
|
|
211
|
+
if (lastItem.variant?.sku !== mutation.listItem.variant.sku) {
|
|
212
|
+
throw new Error("The added line item is not the last item in the list, cannot reliably determine the identifier of the added item");
|
|
213
|
+
}
|
|
214
|
+
return success(this.parseProductListItem(mutation.list, lastItem));
|
|
215
|
+
}
|
|
216
|
+
async deleteItem(mutation) {
|
|
217
|
+
const client = await this.getClient();
|
|
218
|
+
const update = {
|
|
219
|
+
version: 0,
|
|
220
|
+
// The auto-correcting middleware will deal with the version
|
|
221
|
+
actions: [{
|
|
222
|
+
action: "removeLineItem",
|
|
223
|
+
lineItemId: mutation.listItem.key
|
|
224
|
+
}]
|
|
225
|
+
};
|
|
226
|
+
await client.shoppingLists().withId({ ID: mutation.listItem.list.key }).post({ body: update }).execute();
|
|
227
|
+
return success(void 0);
|
|
228
|
+
}
|
|
229
|
+
async updateItem(mutation) {
|
|
230
|
+
const client = await this.getClient();
|
|
231
|
+
const actions = [];
|
|
232
|
+
if (mutation.quantity !== void 0) {
|
|
233
|
+
actions.push({
|
|
234
|
+
action: "changeLineItemQuantity",
|
|
235
|
+
lineItemId: mutation.listItem.key,
|
|
236
|
+
quantity: mutation.quantity
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
if (mutation.notes !== void 0) {
|
|
240
|
+
actions.push({
|
|
241
|
+
action: "setLineItemCustomField",
|
|
242
|
+
lineItemId: mutation.listItem.key,
|
|
243
|
+
name: "notes",
|
|
244
|
+
value: mutation.notes
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
if (mutation.order !== void 0) {
|
|
248
|
+
actions.push({
|
|
249
|
+
action: "setLineItemCustomField",
|
|
250
|
+
lineItemId: mutation.listItem.key,
|
|
251
|
+
name: "order",
|
|
252
|
+
value: mutation.order
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
const update = {
|
|
256
|
+
version: 0,
|
|
257
|
+
actions
|
|
258
|
+
};
|
|
259
|
+
const response = await client.shoppingLists().withId({ ID: mutation.listItem.list.key }).post({ body: update, queryArgs: { expand: "lineItems[*].variant" } }).execute();
|
|
260
|
+
const updatedLineItem = response.body.lineItems.find((item) => item.id === mutation.listItem.key);
|
|
261
|
+
if (!updatedLineItem) {
|
|
262
|
+
throw new Error("Failed to find the updated line item in response");
|
|
263
|
+
}
|
|
264
|
+
return success(this.parseProductListItem(mutation.listItem.list, updatedLineItem));
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* It is not clear to me, why i'd want my CUSTOMER defined resources to be localized, since that means, if he changes visual language,
|
|
268
|
+
* the names of his lists will disappear, since they are not translated. But maybe there are usecases for this, so we should support it, but default to english.
|
|
269
|
+
**/
|
|
270
|
+
getLocaleString() {
|
|
271
|
+
return "en";
|
|
272
|
+
}
|
|
273
|
+
parseSingle(list) {
|
|
274
|
+
const localeString = this.getLocaleString();
|
|
275
|
+
const listType = list.custom?.fields["listType"] || "favorite";
|
|
276
|
+
const image = list.custom?.fields["imageUrl"];
|
|
277
|
+
const published = list.custom?.fields["published"] && true;
|
|
278
|
+
const publishDateDate = list.custom?.fields["publishedDate"];
|
|
279
|
+
let publishedDate;
|
|
280
|
+
if (publishDateDate) {
|
|
281
|
+
publishedDate = new Date(publishDateDate).toISOString();
|
|
282
|
+
}
|
|
283
|
+
return {
|
|
284
|
+
identifier: {
|
|
285
|
+
listType,
|
|
286
|
+
key: list.id
|
|
287
|
+
},
|
|
288
|
+
type: listType,
|
|
289
|
+
name: list.name[localeString] || "Unnamed List",
|
|
290
|
+
description: list.description?.[localeString] || "",
|
|
291
|
+
published,
|
|
292
|
+
publishDate: publishedDate,
|
|
293
|
+
image: {
|
|
294
|
+
sourceUrl: image || "",
|
|
295
|
+
altText: list.name[localeString] || "List Image"
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
parseProductListItem(listIdentifier, lineItem) {
|
|
300
|
+
const localeString = this.getLocaleString();
|
|
301
|
+
return {
|
|
302
|
+
identifier: {
|
|
303
|
+
list: listIdentifier,
|
|
304
|
+
key: lineItem.id
|
|
305
|
+
},
|
|
306
|
+
variant: {
|
|
307
|
+
sku: lineItem.variant?.sku || ""
|
|
308
|
+
},
|
|
309
|
+
quantity: lineItem.quantity,
|
|
310
|
+
notes: lineItem.custom?.fields["notes"] || "",
|
|
311
|
+
order: lineItem.custom?.fields["order"] || 1
|
|
312
|
+
// Commercetools doesn't have explicit ordering
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
__decorateClass([
|
|
317
|
+
Reactionary({
|
|
318
|
+
cache: true,
|
|
319
|
+
cacheTimeToLiveInSeconds: 300,
|
|
320
|
+
currencyDependentCaching: false,
|
|
321
|
+
localeDependentCaching: false,
|
|
322
|
+
inputSchema: ProductListQueryByIdSchema,
|
|
323
|
+
outputSchema: ProductListSchema
|
|
324
|
+
})
|
|
325
|
+
], CommercetoolsProductListProvider.prototype, "getById", 1);
|
|
326
|
+
__decorateClass([
|
|
327
|
+
Reactionary({
|
|
328
|
+
cache: true,
|
|
329
|
+
cacheTimeToLiveInSeconds: 300,
|
|
330
|
+
currencyDependentCaching: false,
|
|
331
|
+
localeDependentCaching: false,
|
|
332
|
+
inputSchema: ProductListQuerySchema,
|
|
333
|
+
outputSchema: ProductListPaginatedResultsSchema
|
|
334
|
+
})
|
|
335
|
+
], CommercetoolsProductListProvider.prototype, "queryLists", 1);
|
|
336
|
+
__decorateClass([
|
|
337
|
+
Reactionary({
|
|
338
|
+
cache: false,
|
|
339
|
+
// Mutations should not be cached
|
|
340
|
+
inputSchema: ProductListMutationCreateSchema,
|
|
341
|
+
outputSchema: ProductListSchema
|
|
342
|
+
})
|
|
343
|
+
], CommercetoolsProductListProvider.prototype, "addList", 1);
|
|
344
|
+
__decorateClass([
|
|
345
|
+
Reactionary({
|
|
346
|
+
cache: false,
|
|
347
|
+
inputSchema: ProductListMutationUpdateSchema,
|
|
348
|
+
outputSchema: ProductListSchema
|
|
349
|
+
})
|
|
350
|
+
], CommercetoolsProductListProvider.prototype, "updateList", 1);
|
|
351
|
+
__decorateClass([
|
|
352
|
+
Reactionary({
|
|
353
|
+
cache: false,
|
|
354
|
+
inputSchema: ProductListMutationDeleteSchema
|
|
355
|
+
})
|
|
356
|
+
], CommercetoolsProductListProvider.prototype, "deleteList", 1);
|
|
357
|
+
__decorateClass([
|
|
358
|
+
Reactionary({
|
|
359
|
+
cache: true,
|
|
360
|
+
cacheTimeToLiveInSeconds: 300,
|
|
361
|
+
currencyDependentCaching: false,
|
|
362
|
+
localeDependentCaching: false,
|
|
363
|
+
inputSchema: ProductListItemQuerySchema,
|
|
364
|
+
outputSchema: ProductListItemPaginatedResultsSchema
|
|
365
|
+
})
|
|
366
|
+
], CommercetoolsProductListProvider.prototype, "queryListItems", 1);
|
|
367
|
+
__decorateClass([
|
|
368
|
+
Reactionary({
|
|
369
|
+
cache: false,
|
|
370
|
+
inputSchema: ProductListItemMutationCreateSchema,
|
|
371
|
+
outputSchema: ProductListItemSchema
|
|
372
|
+
})
|
|
373
|
+
], CommercetoolsProductListProvider.prototype, "addItem", 1);
|
|
374
|
+
__decorateClass([
|
|
375
|
+
Reactionary({
|
|
376
|
+
cache: false,
|
|
377
|
+
inputSchema: ProductListItemMutationDeleteSchema
|
|
378
|
+
})
|
|
379
|
+
], CommercetoolsProductListProvider.prototype, "deleteItem", 1);
|
|
380
|
+
__decorateClass([
|
|
381
|
+
Reactionary({
|
|
382
|
+
cache: false,
|
|
383
|
+
inputSchema: ProductListItemMutationUpdateSchema,
|
|
384
|
+
outputSchema: ProductListItemSchema
|
|
385
|
+
})
|
|
386
|
+
], CommercetoolsProductListProvider.prototype, "updateItem", 1);
|
|
387
|
+
export {
|
|
388
|
+
CommercetoolsProductListProvider
|
|
389
|
+
};
|
|
@@ -7,8 +7,12 @@ const CommercetoolsConfigurationSchema = z.looseObject({
|
|
|
7
7
|
clientId: z.string(),
|
|
8
8
|
clientSecret: z.string(),
|
|
9
9
|
scopes: z.array(z.string()).default(() => []),
|
|
10
|
+
adminClientId: z.string().optional(),
|
|
11
|
+
adminClientSecret: z.string().optional(),
|
|
10
12
|
paymentMethods: PaymentMethodSchema.array().optional().default(() => []),
|
|
11
|
-
facetFieldsForSearch: z.array(z.string()).default(() => [])
|
|
13
|
+
facetFieldsForSearch: z.array(z.string()).default(() => []),
|
|
14
|
+
listPriceChannelKey: z.string().optional(),
|
|
15
|
+
customerPriceChannelKey: z.string().optional()
|
|
12
16
|
});
|
|
13
17
|
export {
|
|
14
18
|
CommercetoolsConfigurationSchema
|
package/src/core/client.d.ts
CHANGED
|
@@ -3,15 +3,31 @@ import { type ApiRoot } from '@commercetools/platform-sdk';
|
|
|
3
3
|
import type { CommercetoolsConfiguration } from '../schema/configuration.schema.js';
|
|
4
4
|
import { type AnonymousIdentity, type GuestIdentity, type RegisteredIdentity, type RequestContext } from '@reactionary/core';
|
|
5
5
|
import { RequestContextTokenCache } from './token-cache.js';
|
|
6
|
+
import { type CommercetoolsSession } from '../schema/session.schema.js';
|
|
7
|
+
export declare const PROVIDER_SESSION_KEY = "COMMERCETOOLS_PROVIDER";
|
|
6
8
|
export declare class CommercetoolsAPI {
|
|
7
9
|
protected config: CommercetoolsConfiguration;
|
|
8
10
|
protected context: RequestContext;
|
|
9
|
-
protected
|
|
11
|
+
protected tokenCache: RequestContextTokenCache;
|
|
10
12
|
protected client: Promise<ApiRoot> | undefined;
|
|
11
13
|
protected adminClient: Promise<ApiRoot> | undefined;
|
|
12
14
|
constructor(config: CommercetoolsConfiguration, context: RequestContext);
|
|
13
15
|
getClient(): Promise<ApiRoot>;
|
|
14
16
|
getAdminClient(): Promise<ApiRoot>;
|
|
17
|
+
getSessionData(): CommercetoolsSession;
|
|
18
|
+
setSessionData(sessionData: Partial<CommercetoolsSession>): void;
|
|
19
|
+
/**
|
|
20
|
+
* Only caches it pr session for now...... but still better than every call
|
|
21
|
+
* @param key
|
|
22
|
+
* @returns
|
|
23
|
+
*/
|
|
24
|
+
resolveChannelIdByKey(key: string): Promise<string>;
|
|
25
|
+
/**
|
|
26
|
+
* Only caches it pr session for now...... but still better than every call
|
|
27
|
+
* @param key
|
|
28
|
+
* @returns
|
|
29
|
+
*/
|
|
30
|
+
resolveChannelIdByRole(role: string): Promise<string>;
|
|
15
31
|
protected createAdminClient(): Promise<ApiRoot>;
|
|
16
32
|
protected createClient(): Promise<ApiRoot>;
|
|
17
33
|
register(username: string, password: string): Promise<{
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { TokenCache, TokenCacheOptions, TokenStore } from "@commercetools/ts-client";
|
|
2
2
|
import type { RequestContext } from "@reactionary/core";
|
|
3
|
-
export declare const PROVIDER_COMMERCETOOLS_SESSION_KEY = "PROVIDER_COMMERCETOOLS";
|
|
4
3
|
export declare class RequestContextTokenCache implements TokenCache {
|
|
5
4
|
protected context: RequestContext;
|
|
6
|
-
|
|
5
|
+
protected sessionProviderKey: string;
|
|
6
|
+
constructor(context: RequestContext, sessionProviderKey: string);
|
|
7
7
|
get(tokenCacheOptions?: TokenCacheOptions): Promise<TokenStore | undefined>;
|
|
8
8
|
set(cache: TokenStore, tokenCacheOptions?: TokenCacheOptions): Promise<void>;
|
|
9
9
|
}
|
package/src/providers/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export * from './inventory.provider.js';
|
|
|
5
5
|
export * from './order-search.provider.js';
|
|
6
6
|
export * from './price.provider.js';
|
|
7
7
|
export * from './product-associations.provider.js';
|
|
8
|
+
export * from './product-list.provider.js';
|
|
8
9
|
export * from './product.provider.js';
|
|
9
10
|
export * from './product-reviews.provider.js';
|
|
10
11
|
export * from './profile.provider.js';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ShoppingList, ShoppingListLineItem } from '@commercetools/platform-sdk';
|
|
2
|
+
import type { Cache, ProductList, ProductListIdentifier, ProductListItem, ProductListItemMutationCreate, ProductListItemMutationDelete, ProductListItemMutationUpdate, ProductListItemPaginatedResult, ProductListItemsQuery, ProductListMutationCreate, ProductListMutationDelete, ProductListMutationUpdate, ProductListPaginatedResult, ProductListQuery, ProductListQueryById, RequestContext, Result } from '@reactionary/core';
|
|
3
|
+
import { ProductListProvider } from '@reactionary/core';
|
|
4
|
+
import type { CommercetoolsAPI } from '../core/client.js';
|
|
5
|
+
import type { CommercetoolsConfiguration } from '../schema/configuration.schema.js';
|
|
6
|
+
export declare class CommercetoolsProductListProvider extends ProductListProvider {
|
|
7
|
+
protected config: CommercetoolsConfiguration;
|
|
8
|
+
protected commercetools: CommercetoolsAPI;
|
|
9
|
+
constructor(config: CommercetoolsConfiguration, cache: Cache, context: RequestContext, commercetools: CommercetoolsAPI);
|
|
10
|
+
protected getClient(): Promise<import("@commercetools/platform-sdk").ByProjectKeyMeRequestBuilder>;
|
|
11
|
+
getById(payload: ProductListQueryById): Promise<Result<ProductList>>;
|
|
12
|
+
queryLists(payload: ProductListQuery): Promise<Result<ProductListPaginatedResult>>;
|
|
13
|
+
addList(mutation: ProductListMutationCreate): Promise<Result<ProductList>>;
|
|
14
|
+
updateList(mutation: ProductListMutationUpdate): Promise<Result<ProductList>>;
|
|
15
|
+
deleteList(mutation: ProductListMutationDelete): Promise<Result<void>>;
|
|
16
|
+
queryListItems(query: ProductListItemsQuery): Promise<Result<ProductListItemPaginatedResult>>;
|
|
17
|
+
addItem(mutation: ProductListItemMutationCreate): Promise<Result<ProductListItem>>;
|
|
18
|
+
deleteItem(mutation: ProductListItemMutationDelete): Promise<Result<void>>;
|
|
19
|
+
updateItem(mutation: ProductListItemMutationUpdate): Promise<Result<ProductListItem>>;
|
|
20
|
+
/**
|
|
21
|
+
* It is not clear to me, why i'd want my CUSTOMER defined resources to be localized, since that means, if he changes visual language,
|
|
22
|
+
* the names of his lists will disappear, since they are not translated. But maybe there are usecases for this, so we should support it, but default to english.
|
|
23
|
+
**/
|
|
24
|
+
protected getLocaleString(): string;
|
|
25
|
+
protected parseSingle(list: ShoppingList): ProductList;
|
|
26
|
+
protected parseProductListItem(listIdentifier: ProductListIdentifier, lineItem: ShoppingListLineItem): ProductListItem;
|
|
27
|
+
}
|
|
@@ -13,6 +13,7 @@ export declare const CommercetoolsCapabilitiesSchema: z.ZodObject<{
|
|
|
13
13
|
productSearch: z.ZodOptional<z.ZodBoolean>;
|
|
14
14
|
productAssociations: z.ZodOptional<z.ZodBoolean>;
|
|
15
15
|
productReviews: z.ZodOptional<z.ZodBoolean>;
|
|
16
|
+
productList: z.ZodOptional<z.ZodBoolean>;
|
|
16
17
|
orderSearch: z.ZodOptional<z.ZodBoolean>;
|
|
17
18
|
}, z.core.$loose>;
|
|
18
19
|
export type CommercetoolsCapabilities = z.infer<typeof CommercetoolsCapabilitiesSchema>;
|
|
@@ -6,6 +6,8 @@ export declare const CommercetoolsConfigurationSchema: z.ZodObject<{
|
|
|
6
6
|
clientId: z.ZodString;
|
|
7
7
|
clientSecret: z.ZodString;
|
|
8
8
|
scopes: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
9
|
+
adminClientId: z.ZodOptional<z.ZodString>;
|
|
10
|
+
adminClientSecret: z.ZodOptional<z.ZodString>;
|
|
9
11
|
paymentMethods: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
10
12
|
identifier: z.ZodObject<{
|
|
11
13
|
method: z.ZodString;
|
|
@@ -22,5 +24,7 @@ export declare const CommercetoolsConfigurationSchema: z.ZodObject<{
|
|
|
22
24
|
isPunchOut: z.ZodBoolean;
|
|
23
25
|
}, z.core.$loose>>>>;
|
|
24
26
|
facetFieldsForSearch: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
27
|
+
listPriceChannelKey: z.ZodOptional<z.ZodString>;
|
|
28
|
+
customerPriceChannelKey: z.ZodOptional<z.ZodString>;
|
|
25
29
|
}, z.core.$loose>;
|
|
26
30
|
export type CommercetoolsConfiguration = z.infer<typeof CommercetoolsConfigurationSchema>;
|