shopware/frontends - api-client
Dynamic and fully typed API Client for Shopware 6. Usable in any JavaScript and TypeScript project.
You can use types generated from your custom API instance to have autocompletion and type safety.
To generate your own types use @shopware/api-gen CLI.
Setup
Install npm package:
npx nypm install @shopware/api-client
npm install @shopware/api-client
yarn add @shopware/api-client
pnpm install @shopware/api-client
bun install @shopware/api-client
Store API client setup
Recommended practice is to create a separate module file. For example src/apiClient.ts
, and import it whenever you need to use API Client.
import { createAPIClient } from "@shopware/api-client";
import type { operations } from "@shopware/api-client/store-api-types";
import type { operations } from "./api-types/storeApiTypes";
import Cookies from "js-cookie";
export const apiClient = createAPIClient<operations>({
baseURL: "https://demo-frontends.shopware.store/store-api",
accessToken: "SWSCBHFSNTVMAWNZDNFKSHLAYW",
contextToken: Cookies.get("sw-context-token"),
});
apiClient.hook("onContextChanged", (newContextToken) => {
Cookies.set("sw-context-token", newContextToken, {
expires: 365,
path: "/",
sameSite: "lax",
secure: shopwareEndpoint.startsWith("https://"),
});
});
Admin API client setup
import { createAdminAPIClient } from "@shopware/api-client";
The setup works the same way as creteAPIClient
function, with few differences
credentials (optional) - Quick scripting or token-based authentication
We provide optional credentials
parameter to createAdminAPIClient
. Which allows you to use authentication type of your choice whenever you wish to create connection to any endpoint.
Example:
import type {
operations,
} from "@shopware/api-client/admin-api-types";
import type { operations } from "./api-types/adminApiTypes";
const adminApiClient = createAdminAPIClient<operations>({
baseURL: `${process.env.SHOP_URL}/api`,
credentials: {
grant_type: "password",
client_id: "administration",
scopes: "write",
username: process.env.SHOP_ADMIN_USERNAME,
password: process.env.SHOP_ADMIN_PASSWORD,
},
});
await adminApiClient.invoke(...);
sessionData (optional) - Persistent authentication
This parameter is used to store session data in cookies (or other place you want to store it), so you can keep your session persistent.
You can combine this option with credentials
property.
import { createAdminAPIClient } from "@shopware/api-client";
import { createAdminAPIClient } from "@shopware/api-client";
import type { operations, Schemas } from "@shopware/api-client/admin-api-types";
import Cookies from "js-cookie";
export const adminApiClient = createAdminAPIClient<operations>({
baseURL: "https://demo-frontends.shopware.store/api",
sessionData: JSON.parse(Cookies.get("sw-admin-session-data") || "{}"),
});
adminApiClient.hooks("onAuthChange", (sessionData) => {
Cookies.set("sw-admin-session-data", JSON.stringify(sessionData), {
expires: 1,
path: "/",
sameSite: "lax",
secure: shopwareEndpoint.startsWith("https://"),
});
});
the rest works the same as store-api client.
Basic usage
Take a look at example project using API Client.
Simple invocation
import { apiClient, RequestReturnType } from "./apiClient";
let productsResponse: RequestReturnType<"readProduct">;
async function loadProducts() {
productsResponse = await apiClient.invoke("readProduct post /product", {
limit: 2,
});
}
Fetch features
The new API client is leveraging ofetch library, which has built in support for AbortController, timeout and other features.
Example usage of AbortController to cancell your request:
const controller = new AbortController();
const request = client.invoke("readContext get /context", {
fetchOptions: {
signal: controller.signal,
},
});
controller.abort();
Other example of using fetchOptions
for setting the timeout:
const request = client.invoke("readContext get /context", {
fetchOptions: {
timeout: 5000,
},
});
All exposed options available under fetchOptions
are:
cache
duplex
keepalive
priority
redirect
retry
retryDelay
retryStatusCodes
signal
timeout
Predefining methods
If you prefer to add another layer of abstraction you can use created previously types to define your own concept of methods.
const readNavigation = ({
depth,
type,
}: {
depth: number;
type: "main-navigation";
}) =>
apiClient.invoke("readNavigation post /navigation/{activeId}/{rootId}", {
headers: {
"sw-include-seo-urls": true,
},
pathParams: {
activeId: type,
rootId: type,
},
body: {
depth,
},
});
import { readNavigation } from "./apiClient";
async function loadMainNavigation() {
const navigation = await readNavigation({
body: { activeId: "main-navigation", rootId: "main-navigation" },
});
}
Error handling
Client is throwing ApiClientError
with detailed information returned from the API. It will display clear message in the console or you can access details
property to get raw information from the response.
import { ApiClientError } from "@shopware/api-client";
try {
} catch (error) {
if (error instanceof ApiClientError) {
console.error(error);
console.error("Details:", error.details);
} else {
console.error("==>", error);
}
}
Links
Changelog
Full changelog for stable version is available here
Latest changes: 0.0.0-canary-20240625121633
Major Changes
Minor Changes
-
#1039 2343012
Thanks @patzick! - We're exposing fetchOptions
inside params of invoke
method. You can now use ofetch
features like timeout
or signal
with AbortController
Example for the AbortController:
const controller = new AbortController();
const request = client.invoke("readContext get /context", {
fetchOptions: {
signal: controller.signal,
},
});
controller.abort();
-
#560 9643e56
Thanks @patzick! - [createAdminAPIClient] ability to pass optional field credentials
to be used as authentication method before invoking any Admin API endpoint.
-
#639 d60d062
Thanks @patzick! - Management of defaultHeaders. You can now set them on apiClient init or runtime.
const apiClient = createApiClient({
...,
defaultHeaders: {
'sw-language-id': 'my-id',
},
});
console.log('Debug default headers:', apiClient.defaultHeaders);
apiClient.defaultHeaders['sw-language-id'] = 'my-new-id';
apiClient.defaultHeaders['sw-language-id'] = "";
apiClient.defaultHeaders.apply({
'sw-language-id': 'another-id',
'sw-currency-id': 'currency-id',
})
-
#857 864616f
Thanks @mdanilowicz! - Add error and success callbacks
Patch Changes