headless-js-api
Version:
Headless JS client for Ecwid public API
293 lines (276 loc) • 8.72 kB
JavaScript
import {
getShouldUseMocks,
getStoreId
} from "./chunk-FT7QP2YK.js";
import {
__require
} from "./chunk-3RG5ZIWI.js";
// src/client/consts.ts
var API_BASE_URL = "https://app.ecwid.com/api/v3/";
var API_TIMEOUT = 1e4;
var API_CACHE_DURATION = 500;
var ONGOING_REQUESTS = /* @__PURE__ */ new Map();
// src/config/index.ts
var apiConfig;
var getApiConfig = () => {
if (apiConfig === void 0) {
throw new Error("Error initializing Storefront API: Please call initStorefrontApi() method first.");
}
return apiConfig;
};
var initStorefrontApi = async (config) => {
var _a, _b, _c, _d;
if (config.publicToken === void 0) {
throw new Error("Error initializing Storefront API: publicToken is required");
}
const storeId = (_a = config.storeId) != null ? _a : await getStoreId();
if (storeId === void 0) {
throw new Error("Error initializing Storefront API: storeId id is not found");
}
const shouldUseMocks = (_c = (_b = getShouldUseMocks()) != null ? _b : config.useMocks) != null ? _c : false;
apiConfig = {
baseURL: (_d = config.baseURL) != null ? _d : API_BASE_URL,
publicToken: config.publicToken,
storeId,
useMocks: shouldUseMocks
};
};
// src/client/instance.ts
import axios from "axios";
var axiosInstance;
try {
axiosInstance = __require("axios");
} catch {
axiosInstance = axios;
}
var instance_default = axiosInstance;
// src/client/request-interceptor.ts
import axios3, { CanceledError as CanceledError2 } from "axios";
// src/client/utils.ts
import axios2 from "axios";
function generateRequestKey(config) {
const {
url,
method,
params = {},
data = {}
} = config;
return `${method == null ? void 0 : method.toUpperCase()}:${url}:${JSON.stringify(params)}:${JSON.stringify(data)}`;
}
function isErrorWithExistingPromise(error) {
return axios2.isCancel(error) && "existingPromise" in error && error.existingPromise !== void 0;
}
// src/client/request-interceptor.ts
function cleanupOldRequests(now) {
Object.entries(ONGOING_REQUESTS).forEach(([key, req]) => {
if (now - req.timestamp > API_CACHE_DURATION) {
ONGOING_REQUESTS.delete(key);
}
});
}
function onFulfilled(config) {
const key = generateRequestKey(config);
const now = Date.now();
cleanupOldRequests(now);
const existingRequest = ONGOING_REQUESTS.get(key);
if (existingRequest) {
const error = new CanceledError2(`Duplicate request: ${key}`);
error.existingPromise = existingRequest.promise;
return Promise.reject(error);
}
const source = axios3.CancelToken.source();
config.cancelToken = source.token;
const requestPromise = new Promise((resolve, reject) => {
config.resolvePromise = resolve;
config.rejectPromise = reject;
});
ONGOING_REQUESTS.set(key, { promise: requestPromise, timestamp: now });
return config;
}
function onRejected(error) {
return Promise.reject(error);
}
var request_interceptor_default = { onFulfilled, onRejected };
// src/client/response-interceptor.ts
function onFulfilled2(response) {
const key = generateRequestKey(response.config);
const requestData = ONGOING_REQUESTS.get(key);
if (requestData) {
const resolve = response.config.resolvePromise;
if (resolve) {
resolve(response);
}
ONGOING_REQUESTS.set(key, { ...requestData, timestamp: Date.now() });
}
return response;
}
function onRejected2(error) {
if (isErrorWithExistingPromise(error)) {
return error.existingPromise;
}
if (error.config) {
const key = generateRequestKey(error.config);
const requestData = ONGOING_REQUESTS.get(key);
if (requestData) {
const reject = error.config.rejectPromise;
if (reject) {
reject(error);
}
ONGOING_REQUESTS.set(key, { ...requestData, timestamp: Date.now() });
}
}
return Promise.reject(error);
}
var response_interceptor_default = { onFulfilled: onFulfilled2, onRejected: onRejected2 };
// src/client/mock-registry.ts
var MOCK_REGISTRY = {
["GetStoreProfile" /* GetStoreProfile */]: () => import("./get-store-profile-mock-WZLDHIMW.js"),
["GetProduct" /* GetProduct */]: () => import("./get-product-mock-H2L5QXVE.js"),
["SearchProducts" /* SearchProducts */]: () => import("./search-products-mock-OEC3UZCO.js"),
["DownloadProductFile" /* DownloadProductFile */]: () => import("./download-product-file-mock-H6CV5VEL.js"),
["SearchCategories" /* SearchCategories */]: () => import("./search-categories-mock-POXLG2SB.js")
};
// src/client/mocks-interceptor.ts
async function resolveMockResponse(mockRequest) {
if (!mockRequest) {
return Promise.resolve({
message: "Please provide a valid mock request"
});
}
if (!MOCK_REGISTRY[mockRequest]) {
return Promise.resolve({
message: `Mock request "${mockRequest}" not found`
});
}
return (await MOCK_REGISTRY[mockRequest]()).default;
}
async function onFulfilled3(config) {
return Promise.reject({
status: 200,
data: await resolveMockResponse(config.mockRequest),
statusText: "Ok",
headers: {}
});
}
function onRejected3(error) {
return Promise.resolve({
status: error.status,
data: error.data,
statusText: error.statusText,
headers: error.headers
});
}
var mocks_interceptor_default = { onFulfilled: onFulfilled3, onRejected: onRejected3 };
// src/client/index.ts
var axiosInstance2 = null;
function createInstance() {
const config = getApiConfig();
const instance = instance_default.create({
timeout: API_TIMEOUT,
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${config.publicToken}`
}
});
instance.interceptors.request.use(
request_interceptor_default.onFulfilled,
request_interceptor_default.onRejected
);
instance.interceptors.response.use(
response_interceptor_default.onFulfilled,
response_interceptor_default.onRejected
);
if (config.useMocks) {
instance.interceptors.request.use(
mocks_interceptor_default.onFulfilled
);
instance.interceptors.response.use(
(response) => response,
mocks_interceptor_default.onRejected
);
}
return instance;
}
var getApiClient = () => {
if (axiosInstance2 === null) {
axiosInstance2 = createInstance();
}
return axiosInstance2;
};
// src/api/products/requests/search-products/index.ts
var searchProducts = async (params) => {
const apiClient = getApiClient();
const { storeId, baseURL } = getApiConfig();
const options = {
mockRequest: "SearchProducts" /* SearchProducts */
};
if (params !== void 0) {
options.params = params;
}
const url = `${baseURL}${storeId}/products`;
const response = await apiClient.get(url, options);
return response.data;
};
// src/api/products/requests/get-product/index.ts
var getProduct = async (params) => {
const apiClient = getApiClient();
const { storeId, baseURL } = getApiConfig();
const { productId, ...queryParams } = params;
const options = {
params: queryParams,
mockRequest: "GetProduct" /* GetProduct */
};
const url = `${baseURL}${storeId}/products/${productId}`;
const response = await apiClient.get(url, options);
return response.data;
};
// src/api/products/requests/download-product-file/index.ts
var downloadProductFile = async (params) => {
const apiClient = getApiClient();
const { storeId, baseURL } = getApiConfig();
const { productId, fileId } = params;
const options = {
responseType: "blob",
mockRequest: "DownloadProductFile" /* DownloadProductFile */
};
const url = `${baseURL}${storeId}/products/${productId}/files/${fileId}`;
const response = await apiClient.get(url, options);
return response.data;
};
// src/api/categories/requests/search-categories/index.ts
var searchCategories = async (params) => {
const apiClient = getApiClient();
const { storeId, baseURL } = getApiConfig();
const options = {
mockRequest: "SearchCategories" /* SearchCategories */
};
if (params !== void 0) {
options.params = params;
}
const url = `${baseURL}${storeId}/categories`;
const response = await apiClient.get(url, options);
return response.data;
};
// src/api/store/requests/get-store-profile/index.ts
var getStoreProfile = async (params) => {
const apiClient = getApiClient();
const { storeId, baseURL } = getApiConfig();
const options = {
mockRequest: "GetStoreProfile" /* GetStoreProfile */
};
if (params !== void 0) {
options.params = params;
}
const url = `${baseURL}${storeId}/profile`;
const response = await apiClient.get(url, options);
return response.data;
};
export {
getApiConfig,
initStorefrontApi,
searchProducts,
getProduct,
downloadProductFile,
searchCategories,
getStoreProfile
};