@builder.io/plugin-commercelayer 0.0.8-0 → 0.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.
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
- - Market Scope (e.g., 'market:id:YOUR_MARKET_ID')
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 uses Commerce Layer's Sales Channel authentication. You'll need:
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
- - A valid market scope
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
 
@@ -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.7";
146884
+ var version = "0.0.9-1";
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
- const authenticateClient = async ({ clientId, scope }) => {
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
- console.log("Authenticating with:", { clientId, scope });
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
- console.error("API Error:", { status: response.status, statusText: response.statusText, errorText, url });
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
- console.log("Plugin initializing with:", { clientId, scope });
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 product = await getProduct(id, auth.accessToken, baseEndpoint);
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 product = await getProductByHandle(handle, auth.accessToken, baseEndpoint);
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
- console.log("Searching for:", search);
147089
- const products = await searchProducts(search, auth.accessToken, baseEndpoint);
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 ${auth.accessToken}`
147117
+ "Authorization": `Bearer ${token}`
147100
147118
  }
147101
147119
  },
147102
147120
  options: {