@builder.io/plugin-commercelayer 0.0.8-0 → 0.0.8-1
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 +16 -4
- package/dist/plugin.system.js +47 -29
- package/dist/plugin.system.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,7 +6,8 @@ Easily connect your Commerce Layer products to your Builder.io content!
|
|
|
6
6
|
|
|
7
7
|
Go to [builder.io/account/organization](https://builder.io/account/organization) and press on `@builder.io/plugin-commercelayer` in the list of plugins, then hit save. You'll be prompted for your Commerce Layer credentials:
|
|
8
8
|
- Client ID
|
|
9
|
-
-
|
|
9
|
+
- Client Secret (optional - required for integration tokens to access all markets)
|
|
10
|
+
- Market Scope (e.g., 'market:all' for integrations, 'market:id:YOUR_MARKET_ID' for sales channels)
|
|
10
11
|
|
|
11
12
|
## Features
|
|
12
13
|
|
|
@@ -68,10 +69,21 @@ Go to [builder.io/account/organization](https://builder.io/account/organization)
|
|
|
68
69
|
|
|
69
70
|
## Authentication
|
|
70
71
|
|
|
71
|
-
The plugin
|
|
72
|
+
The plugin supports both Commerce Layer authentication methods:
|
|
73
|
+
|
|
74
|
+
### Sales Channel Authentication (Market-Specific)
|
|
75
|
+
For accessing products from a specific market:
|
|
72
76
|
- A Commerce Layer account
|
|
73
|
-
- Sales Channel API credentials
|
|
74
|
-
-
|
|
77
|
+
- Sales Channel API credentials (Client ID only)
|
|
78
|
+
- Market-specific scope (e.g., `market:id:YOUR_MARKET_ID`)
|
|
79
|
+
|
|
80
|
+
### Integration Authentication (All Markets)
|
|
81
|
+
For accessing products from all markets:
|
|
82
|
+
- A Commerce Layer account
|
|
83
|
+
- Integration API credentials (Client ID + Client Secret)
|
|
84
|
+
- Market scope set to `market:all`
|
|
85
|
+
|
|
86
|
+
**Note:** Sales channel tokens with `market:all` scope will not return products due to Commerce Layer restrictions. Use integration tokens for cross-market access.
|
|
75
87
|
|
|
76
88
|
## Contributing
|
|
77
89
|
|
package/dist/plugin.system.js
CHANGED
|
@@ -146881,7 +146881,7 @@ System.register(['@builder.io/sdk', '@emotion/core', '@material-ui/core', 'react
|
|
|
146881
146881
|
});
|
|
146882
146882
|
|
|
146883
146883
|
var name = "@builder.io/plugin-commercelayer";
|
|
146884
|
-
var version = "0.0.
|
|
146884
|
+
var version = "0.0.8-0";
|
|
146885
146885
|
var description = "Commerce Layer plugin for Builder.io";
|
|
146886
146886
|
var keywords = [
|
|
146887
146887
|
];
|
|
@@ -146944,28 +146944,46 @@ System.register(['@builder.io/sdk', '@emotion/core', '@material-ui/core', 'react
|
|
|
146944
146944
|
dependencies: dependencies
|
|
146945
146945
|
};
|
|
146946
146946
|
|
|
146947
|
-
|
|
146947
|
+
let cachedAuth = null;
|
|
146948
|
+
const getValidToken = async (clientId, clientSecret, scope) => {
|
|
146949
|
+
const now = Date.now();
|
|
146950
|
+
if (cachedAuth && cachedAuth.clientId === clientId && cachedAuth.clientSecret === clientSecret && cachedAuth.scope === scope && now < cachedAuth.expiresAt) {
|
|
146951
|
+
return cachedAuth.token;
|
|
146952
|
+
}
|
|
146953
|
+
const auth = await authenticateClient({ clientId, clientSecret, scope });
|
|
146954
|
+
cachedAuth = {
|
|
146955
|
+
token: auth.accessToken,
|
|
146956
|
+
expiresAt: now + (auth.expiresIn - 300) * 1e3,
|
|
146957
|
+
// 5 min buffer
|
|
146958
|
+
clientId,
|
|
146959
|
+
clientSecret,
|
|
146960
|
+
scope
|
|
146961
|
+
};
|
|
146962
|
+
return auth.accessToken;
|
|
146963
|
+
};
|
|
146964
|
+
const authenticateClient = async ({ clientId, clientSecret, scope }) => {
|
|
146948
146965
|
const authUrl = "https://auth.commercelayer.io/oauth/token";
|
|
146949
|
-
|
|
146966
|
+
const requestBody = {
|
|
146967
|
+
grant_type: "client_credentials",
|
|
146968
|
+
client_id: clientId,
|
|
146969
|
+
scope
|
|
146970
|
+
};
|
|
146971
|
+
if (clientSecret) {
|
|
146972
|
+
requestBody.client_secret = clientSecret;
|
|
146973
|
+
}
|
|
146950
146974
|
const response = await fetch(authUrl, {
|
|
146951
146975
|
method: "POST",
|
|
146952
146976
|
headers: {
|
|
146953
146977
|
"Accept": "application/json",
|
|
146954
146978
|
"Content-Type": "application/json"
|
|
146955
146979
|
},
|
|
146956
|
-
body: JSON.stringify(
|
|
146957
|
-
grant_type: "client_credentials",
|
|
146958
|
-
client_id: clientId,
|
|
146959
|
-
scope
|
|
146960
|
-
})
|
|
146980
|
+
body: JSON.stringify(requestBody)
|
|
146961
146981
|
});
|
|
146962
146982
|
if (!response.ok) {
|
|
146963
146983
|
const errorText = await response.text();
|
|
146964
|
-
console.error("Auth Error:", { status: response.status, statusText: response.statusText, errorText });
|
|
146965
146984
|
throw new Error(`Authentication failed: ${response.status} ${response.statusText} - ${errorText}`);
|
|
146966
146985
|
}
|
|
146967
146986
|
const data = await response.json();
|
|
146968
|
-
console.log("Auth response:", data);
|
|
146969
146987
|
return {
|
|
146970
146988
|
accessToken: data.access_token,
|
|
146971
146989
|
tokenType: data.token_type,
|
|
@@ -146975,7 +146993,6 @@ System.register(['@builder.io/sdk', '@emotion/core', '@material-ui/core', 'react
|
|
|
146975
146993
|
};
|
|
146976
146994
|
};
|
|
146977
146995
|
const makeApiRequest = async (url, accessToken, options = {}) => {
|
|
146978
|
-
console.log("Making API request:", { url, tokenLength: accessToken.length });
|
|
146979
146996
|
const response = await fetch(url, {
|
|
146980
146997
|
...options,
|
|
146981
146998
|
headers: {
|
|
@@ -146987,17 +147004,9 @@ System.register(['@builder.io/sdk', '@emotion/core', '@material-ui/core', 'react
|
|
|
146987
147004
|
});
|
|
146988
147005
|
if (!response.ok) {
|
|
146989
147006
|
const errorText = await response.text();
|
|
146990
|
-
|
|
146991
|
-
try {
|
|
146992
|
-
const errorData = JSON.parse(errorText);
|
|
146993
|
-
console.error("Parsed error:", errorData);
|
|
146994
|
-
} catch (e) {
|
|
146995
|
-
console.error("Raw error text:", errorText);
|
|
146996
|
-
}
|
|
146997
|
-
throw new Error(`API request failed: ${response.status} ${response.statusText}`);
|
|
147007
|
+
throw new Error(`API request failed: ${response.status} ${response.statusText} - ${errorText}`);
|
|
146998
147008
|
}
|
|
146999
147009
|
const data = await response.json();
|
|
147000
|
-
console.log("API response:", { url, dataLength: JSON.stringify(data).length });
|
|
147001
147010
|
return data;
|
|
147002
147011
|
};
|
|
147003
147012
|
const getOrganizationInfo = async (accessToken) => {
|
|
@@ -147030,6 +147039,7 @@ System.register(['@builder.io/sdk', '@emotion/core', '@material-ui/core', 'react
|
|
|
147030
147039
|
type: "product",
|
|
147031
147040
|
title: product.attributes.name,
|
|
147032
147041
|
handle: product.attributes.code,
|
|
147042
|
+
price: product.attributes.price,
|
|
147033
147043
|
image: {
|
|
147034
147044
|
src: product.attributes.image_url
|
|
147035
147045
|
}
|
|
@@ -147057,11 +147067,17 @@ System.register(['@builder.io/sdk', '@emotion/core', '@material-ui/core', 'react
|
|
|
147057
147067
|
required: true,
|
|
147058
147068
|
helperText: "Your Commerce Layer application Client ID"
|
|
147059
147069
|
},
|
|
147070
|
+
{
|
|
147071
|
+
name: "clientSecret",
|
|
147072
|
+
type: "string",
|
|
147073
|
+
required: false,
|
|
147074
|
+
helperText: "Your Commerce Layer Client Secret (required for integration tokens to access all markets)"
|
|
147075
|
+
},
|
|
147060
147076
|
{
|
|
147061
147077
|
name: "scope",
|
|
147062
147078
|
type: "string",
|
|
147063
147079
|
required: true,
|
|
147064
|
-
helperText: 'Commerce Layer scope (e.g., "market:all")'
|
|
147080
|
+
helperText: 'Commerce Layer scope (e.g., "market:all" for integrations, "market:id:YOUR_MARKET_ID" for sales channels)'
|
|
147065
147081
|
}
|
|
147066
147082
|
],
|
|
147067
147083
|
ctaText: "Connect your Commerce Layer store"
|
|
@@ -147069,34 +147085,36 @@ System.register(['@builder.io/sdk', '@emotion/core', '@material-ui/core', 'react
|
|
|
147069
147085
|
async (settings) => {
|
|
147070
147086
|
try {
|
|
147071
147087
|
const clientId = settings.get("clientId");
|
|
147088
|
+
const clientSecret = settings.get("clientSecret");
|
|
147072
147089
|
const scope = settings.get("scope");
|
|
147073
|
-
|
|
147074
|
-
const auth = await authenticateClient({ clientId, scope });
|
|
147090
|
+
const auth = await authenticateClient({ clientId, clientSecret, scope });
|
|
147075
147091
|
const { baseEndpoint } = await getOrganizationInfo(auth.accessToken);
|
|
147076
|
-
console.log("Plugin initialized with:", { baseEndpoint, tokenLength: auth.accessToken.length });
|
|
147077
147092
|
return {
|
|
147078
147093
|
product: {
|
|
147079
147094
|
async findById(id) {
|
|
147080
|
-
const
|
|
147095
|
+
const token = await getValidToken(clientId, clientSecret, scope);
|
|
147096
|
+
const product = await getProduct(id, token, baseEndpoint);
|
|
147081
147097
|
return transformProduct(product);
|
|
147082
147098
|
},
|
|
147083
147099
|
async findByHandle(handle) {
|
|
147084
|
-
const
|
|
147100
|
+
const token = await getValidToken(clientId, clientSecret, scope);
|
|
147101
|
+
const product = await getProductByHandle(handle, token, baseEndpoint);
|
|
147085
147102
|
return transformProduct(product);
|
|
147086
147103
|
},
|
|
147087
147104
|
async search(search) {
|
|
147088
|
-
|
|
147089
|
-
const products = await searchProducts(search,
|
|
147105
|
+
const token = await getValidToken(clientId, clientSecret, scope);
|
|
147106
|
+
const products = await searchProducts(search, token, baseEndpoint);
|
|
147090
147107
|
return products.map(transformProduct);
|
|
147091
147108
|
},
|
|
147092
147109
|
getRequestObject(id) {
|
|
147110
|
+
const token = cachedAuth?.token || auth.accessToken;
|
|
147093
147111
|
return {
|
|
147094
147112
|
"@type": "@builder.io/core:Request",
|
|
147095
147113
|
request: {
|
|
147096
147114
|
url: `${baseEndpoint}/api/skus/${id}`,
|
|
147097
147115
|
method: "GET",
|
|
147098
147116
|
headers: {
|
|
147099
|
-
"Authorization": `Bearer ${
|
|
147117
|
+
"Authorization": `Bearer ${token}`
|
|
147100
147118
|
}
|
|
147101
147119
|
},
|
|
147102
147120
|
options: {
|