@shopware/api-client 0.3.0 → 0.5.0

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/dist/index.mjs CHANGED
@@ -1,5 +1,11 @@
1
1
  import { ofetch } from 'ofetch';
2
2
 
3
+ var __defProp = Object.defineProperty;
4
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
5
+ var __publicField = (obj, key, value) => {
6
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
7
+ return value;
8
+ };
3
9
  class ApiClientError extends Error {
4
10
  constructor(response) {
5
11
  let message = "Failed request";
@@ -9,9 +15,33 @@ class ApiClientError extends Error {
9
15
  pointer = `[${error.source.pointer}]`;
10
16
  }
11
17
  return `${message2}
12
- - [${error.title}]${pointer} ${error.detail}`;
18
+ - [${error.title}]${pointer} ${error.detail ?? ""}`;
13
19
  }, "");
14
20
  super(message);
21
+ /**
22
+ * Flag to indicate if the request was successful.
23
+ */
24
+ __publicField(this, "ok");
25
+ /**
26
+ * HTTP status code of the response.
27
+ */
28
+ __publicField(this, "status");
29
+ /**
30
+ * HTTP status text of the response.
31
+ */
32
+ __publicField(this, "statusText");
33
+ /**
34
+ * URL of the request.
35
+ */
36
+ __publicField(this, "url");
37
+ /**
38
+ * Details of the error.
39
+ */
40
+ __publicField(this, "details");
41
+ /**
42
+ * Headers of the response.
43
+ */
44
+ __publicField(this, "headers");
15
45
  this.name = "ApiClientError";
16
46
  this.details = response._data || {
17
47
  errors: [{ title: "Unknown error", detail: "" }]
@@ -27,6 +57,44 @@ function errorInterceptor(response) {
27
57
  throw new ApiClientError(response);
28
58
  }
29
59
 
60
+ function transformPathToQuery(path, params) {
61
+ const [, method, pathDefinition, headerParams] = path.split(" ");
62
+ const [requestPath, queryParams] = pathDefinition.split("?");
63
+ const pathParams = requestPath.match(/{[^}]+}/g)?.map((param) => param.substring(1, param.length - 1)) || [];
64
+ const requestPathWithParams = pathParams.reduce((acc, paramName) => {
65
+ return acc.replace(`{${paramName}}`, params[paramName]);
66
+ }, requestPath);
67
+ const queryParamNames = queryParams?.split(",") || [];
68
+ const headerParamnames = headerParams?.split(",") || [];
69
+ const headers = {};
70
+ headerParamnames.forEach((paramName) => {
71
+ headers[paramName] = params[paramName];
72
+ });
73
+ const query = {};
74
+ queryParamNames.forEach((paramName) => {
75
+ let queryParamName = paramName;
76
+ if (Array.isArray(params[paramName]) && !queryParamName.includes("[]")) {
77
+ queryParamName += "[]";
78
+ }
79
+ query[queryParamName] = params[paramName];
80
+ });
81
+ const returnOptions = {
82
+ method: method.toUpperCase(),
83
+ headers,
84
+ query
85
+ };
86
+ if (!params) {
87
+ return [requestPathWithParams, returnOptions];
88
+ }
89
+ Object.keys(params).forEach((key) => {
90
+ if (!pathParams.includes(key) && !queryParamNames.includes(key) && !headerParamnames.includes(key)) {
91
+ returnOptions.body ?? (returnOptions.body = {});
92
+ Reflect.set(returnOptions.body, key, params[key]);
93
+ }
94
+ });
95
+ return [requestPathWithParams, returnOptions];
96
+ }
97
+
30
98
  function createAPIClient(params) {
31
99
  const defaultHeaders = {
32
100
  "sw-access-key": params.accessToken
@@ -49,10 +117,10 @@ function createAPIClient(params) {
49
117
  errorInterceptor(response);
50
118
  }
51
119
  });
52
- async function invoke(pathParam, params2) {
120
+ async function invoke(pathParam, ...params2) {
53
121
  const [requestPath, options] = transformPathToQuery(
54
122
  pathParam,
55
- params2
123
+ params2?.[0]
56
124
  );
57
125
  return apiFetch(
58
126
  requestPath,
@@ -69,39 +137,105 @@ function createAPIClient(params) {
69
137
  invoke
70
138
  };
71
139
  }
72
- function transformPathToQuery(path, params) {
73
- const [, method, pathDefinition, headerParams] = path.split(" ");
74
- const [requestPath, queryParams] = pathDefinition.split("?");
75
- const pathParams = requestPath.match(/{[^}]+}/g)?.map((param) => param.substring(1, param.length - 1)) || [];
76
- const requestPathWithParams = pathParams.reduce((acc, paramName) => {
77
- return acc.replace(`{${paramName}}`, params[paramName]);
78
- }, requestPath);
79
- const queryParamNames = queryParams?.split(",") || [];
80
- const headerParamnames = headerParams?.split(",") || [];
81
- const headers = {};
82
- headerParamnames.forEach((paramName) => {
83
- headers[paramName] = params[paramName];
84
- });
85
- const query = {};
86
- queryParamNames.forEach((paramName) => {
87
- let queryParamName = paramName;
88
- if (Array.isArray(params[paramName]) && !queryParamName.includes("[]")) {
89
- queryParamName += "[]";
140
+ function createAuthorizationHeader(token) {
141
+ if (!token)
142
+ return null;
143
+ if (token.startsWith("Bearer "))
144
+ return token;
145
+ return `Bearer ${token}`;
146
+ }
147
+ function createAdminAPIClient(params) {
148
+ const sessionData = {
149
+ accessToken: params.sessionData?.accessToken || "",
150
+ refreshToken: params.sessionData?.refreshToken || "",
151
+ expirationTime: Number(params.sessionData?.expirationTime || 0)
152
+ };
153
+ function updateSessionData(responseData) {
154
+ if (responseData?.access_token) {
155
+ defaultHeaders.Authorization = createAuthorizationHeader(
156
+ responseData.access_token
157
+ );
158
+ sessionData.accessToken = responseData.access_token;
159
+ sessionData.refreshToken = responseData.refresh_token;
160
+ sessionData.expirationTime = Date.now() + responseData.expires_in * 1e3;
161
+ params.onAuthChange?.({
162
+ ...sessionData
163
+ });
90
164
  }
91
- query[queryParamName] = params[paramName];
92
- });
93
- const returnOptions = {
94
- method: method.toUpperCase(),
95
- headers,
96
- query
165
+ }
166
+ function setSessionData(data) {
167
+ sessionData.accessToken = data.accessToken;
168
+ sessionData.refreshToken = data.refreshToken;
169
+ sessionData.expirationTime = data.expirationTime;
170
+ return getSessionData();
171
+ }
172
+ function getSessionData() {
173
+ return { ...sessionData };
174
+ }
175
+ const defaultHeaders = {
176
+ Authorization: createAuthorizationHeader(sessionData.accessToken)
97
177
  };
98
- Object.keys(params).forEach((key) => {
99
- if (!pathParams.includes(key) && !queryParamNames.includes(key) && !headerParamnames.includes(key)) {
100
- returnOptions.body ?? (returnOptions.body = {});
101
- Reflect.set(returnOptions.body, key, params[key]);
178
+ const apiFetch = ofetch.create({
179
+ baseURL: params.baseURL,
180
+ async onRequest({ request, options }) {
181
+ const isExpired = sessionData.expirationTime <= Date.now();
182
+ if (isExpired && !request.toString().includes("/oauth/token")) {
183
+ await ofetch("/oauth/token", {
184
+ baseURL: params.baseURL,
185
+ method: "POST",
186
+ body: {
187
+ grant_type: "refresh_token",
188
+ client_id: "administration",
189
+ refresh_token: sessionData.refreshToken || ""
190
+ },
191
+ headers: defaultHeaders,
192
+ onResponseError({ response }) {
193
+ errorInterceptor(response);
194
+ },
195
+ onResponse(context) {
196
+ updateSessionData(context.response._data);
197
+ }
198
+ });
199
+ }
200
+ },
201
+ async onResponse(context) {
202
+ updateSessionData(context.response._data);
203
+ },
204
+ async onResponseError({ request, response, options }) {
205
+ errorInterceptor(response);
102
206
  }
103
207
  });
104
- return [requestPathWithParams, returnOptions];
208
+ async function invoke(pathParam, params2) {
209
+ const [requestPath, options] = transformPathToQuery(
210
+ pathParam,
211
+ params2
212
+ );
213
+ return apiFetch(
214
+ requestPath,
215
+ {
216
+ ...options,
217
+ headers: {
218
+ ...defaultHeaders,
219
+ ...options.headers
220
+ }
221
+ }
222
+ );
223
+ }
224
+ return {
225
+ /**
226
+ * Invoke API request based on provided path definition.
227
+ */
228
+ invoke,
229
+ /**
230
+ * Enables to change session data in runtime. Useful for testing purposes.
231
+ * Setting session data with this methis will **not** fire `onAuthChange` hook.
232
+ */
233
+ setSessionData,
234
+ /**
235
+ * Returns current session data. Useful for testing purposes, as in most cases you'll want to use `onAuthChange` hook for that.
236
+ */
237
+ getSessionData
238
+ };
105
239
  }
106
240
 
107
- export { ApiClientError, createAPIClient, transformPathToQuery };
241
+ export { ApiClientError, createAPIClient, createAdminAPIClient };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shopware/api-client",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "description": "Shopware client for API connection.",
5
5
  "author": "Shopware",
6
6
  "repository": {
@@ -18,25 +18,37 @@
18
18
  },
19
19
  "license": "MIT",
20
20
  "module": "./dist/index.mjs",
21
+ "main": "./dist/index.cjs",
21
22
  "types": "./dist/index.d.ts",
22
23
  "files": [
23
24
  "dist",
24
- "api-types"
25
+ "api-types",
26
+ "admin-api-types"
25
27
  ],
26
28
  "exports": {
27
- "import": "./dist/index.mjs"
29
+ ".": {
30
+ "require": {
31
+ "types": "./dist/index.d.cts",
32
+ "default": "./dist/index.cjs"
33
+ },
34
+ "import": {
35
+ "types": "./dist/index.d.mts",
36
+ "default": "./dist/index.mjs"
37
+ }
38
+ }
28
39
  },
29
40
  "devDependencies": {
30
41
  "@types/prettier": "^3.0.0",
31
42
  "@vitest/coverage-c8": "^0.33.0",
32
- "prettier": "^3.0.0",
33
- "vitest": "^0.33.0",
34
- "@shopware/api-gen": "0.0.6",
35
- "eslint-config-shopware": "0.0.5",
43
+ "prettier": "^3.0.3",
44
+ "unbuild": "^2.0.0",
45
+ "vitest": "^0.34.6",
46
+ "@shopware/api-gen": "0.1.0",
47
+ "eslint-config-shopware": "0.0.7",
36
48
  "tsconfig": "0.0.0"
37
49
  },
38
50
  "dependencies": {
39
- "ofetch": "^1.1.1"
51
+ "ofetch": "^1.3.3"
40
52
  },
41
53
  "scripts": {
42
54
  "build": "export NODE_ENV=production && unbuild && pnpm build:types",