Appearance
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:
sh
# ✨ Auto-detect
npx nypm install @shopware/api-client
# npm
npm install @shopware/api-client
# yarn
yarn add @shopware/api-client
# pnpm
pnpm install @shopware/api-client
# bun
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.
typescript
import { createAPIClient } from "@shopware/api-client";
// You can pick types of your current API version, the default one:
import type { operations } from "@shopware/api-client/store-api-types";
// or - RECOMMENDED - your types generated by [@shopware/api-gen](https://www.npmjs.com/package/@shopware/api-gen) CLI:
import type { operations } from "./api-types/storeApiTypes";
// you can pick cookies library of your choice
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, // days
path: "/",
sameSite: "lax",
secure: shopwareEndpoint.startsWith("https://"),
});
});
Admin API client setup ​
typescript
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:
typescript
import type {
operations,
} from "@shopware/api-client/admin-api-types"; // we take default admin api types from different directory than store-api - use your own types by generating schema with @shopware/api-gen CLI
import type { operations } from "./api-types/adminApiTypes"; // or use your own types generated by @shopware/api-gen CLI
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,
},
// credentials: { // or token-based example
// grant_type: "client_credentials",
// client_id: "administration",
// client_secret: process.env.SHOP_ADMIN_TOKEN,
// },
});
await adminApiClient.invoke(...); // invoke defined endpoint
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.
typescript
// example adminApiClient.ts file
import { createAdminAPIClient } from "@shopware/api-client"; // we use different function to create admin api client
import { createAdminAPIClient } from "@shopware/api-client";
import type { operations, Schemas } from "@shopware/api-client/admin-api-types"; // we take default admin api types from different directory than store-api
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, // days
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 ​
typescript
import { apiClient, RequestReturnType } from "./apiClient";
// could be reactive value, you can use ApiReturnType to type it properly
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:
typescript
const controller = new AbortController();
const request = client.invoke("readContext get /context", {
fetchOptions: {
signal: controller.signal,
},
});
controller.abort(); // At this point client will throw an error with the information, that the request has been cancelled
Other example of using fetchOptions
for setting the timeout:
typescript
const request = client.invoke("readContext get /context", {
fetchOptions: {
timeout: 5000, // 5 seconds
},
});
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.
typescript
// add for example into apiClient.ts file
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,
},
});
// in another file you can use it, and depth property will be set to 2 by default
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.
typescript
import { ApiClientError } from "@shopware/api-client";
try {
// ... your request
} catch (error) {
if (error instanceof ApiClientError) {
console.error(error); // This prints message summary
console.error("Details:", error.details); // Raw response from API
} else {
console.error("==>", error); // Another type of error, not recognized by API client
}
}
Links ​
👥 Community Slack (
#shopware-frontends
channel)
Changelog ​
Full changelog for stable version is available here
Latest changes: 1.0.0 ​
Major Changes ​
#871
1566f7a
Thanks @patzick! - Read more about new major release: https://github.com/shopware/frontends/discussions/965#1056
c729e70
Thanks @patzick! - Removed deprecations from the code:onContextChanged
function insidecreateAPIClient
method. UseapiClient.hook("onContextChanged", ...)
instead.apiType
flag from thecreateAPIClient
. Use separate methods to create store and admin api clientsonAuthChange
from thecreateAdminAPIClient
. UseadminApiClient.hook('onAuthChange',...)
instead
Minor Changes ​
#1039
2343012
Thanks @patzick! - We're exposingfetchOptions
inside params ofinvoke
method. You can now useofetch
features liketimeout
orsignal
with AbortControllerExample for the AbortController:
tsconst controller = new AbortController(); const request = client.invoke("readContext get /context", { fetchOptions: { signal: controller.signal, }, }); controller.abort(); // At this point client will throw an error with the information, that the request has been cancelled
#560
9643e56
Thanks @patzick! - [createAdminAPIClient] ability to pass optional fieldcredentials
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.tsconst apiClient = createApiClient({ ..., defaultHeaders: { 'sw-language-id': 'my-id', }, }); console.log('Debug default headers:', apiClient.defaultHeaders); // Change header runtime apiClient.defaultHeaders['sw-language-id'] = 'my-new-id'; // Remove header runtime apiClient.defaultHeaders['sw-language-id'] = ""; // Change multiple headers runtime apiClient.defaultHeaders.apply({ 'sw-language-id': 'another-id', 'sw-currency-id': 'currency-id', })
#857
864616f
Thanks @mdanilowicz! - Add error and success callbacks
Patch Changes ​
#787
782ef4d
Thanks @mkucmus! - Adjust test snapshot for Shopware v6.6 response#567
1583a7a
Thanks @patzick! - Export default API types to be compatible with thebundler
mode resolution intsconfig
#557
97d2859
Thanks @patzick! - AddedAccept: application/json
default header to get only JSON responses.
API ​
createAPIClient
​
ts
export function createAPIClient<
OPERATIONS extends Record<string, any> = operations,
PATHS extends string | number | symbol = keyof OPERATIONS,
>(params: {
baseURL?: string;
accessToken?: string;
contextToken?: string;
defaultHeaders?: ClientHeaders;
})
createAdminAPIClient
​
ts
export function createAdminAPIClient<
OPERATIONS extends Record<string, any> = operations,
PATHS extends string | number | symbol = keyof OPERATIONS,
>(params: {
baseURL?: string;
/**
* If you pass `credentials` object, it will be used to authenticate the client whenever session expires.
* You don't need to manually invoke `/token` endpoint first.
*/
credentials?: OPERATIONS["token"]["body"];
sessionData?: AdminSessionData;
defaultHeaders?: ClientHeaders;
})
ApiError
​
ts
export type ApiError = {
title?: string;
detail?: string;
code?: string;
status?: string;
source?: {
pointer?: string;
};
meta?: {
parameters?: Record<string, string> | [];
};
};