@shopware/api-client 0.4.0 → 1.0.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/README.md +209 -85
- package/{admin-api-types/apiSchema-6.5.3.0.json → api-types/adminApiSchema.json} +62470 -25854
- package/api-types/adminApiTypes.d.ts +84322 -0
- package/api-types/{apiSchema-6.4.19.0.json → storeApiSchema.json} +15295 -11433
- package/api-types/storeApiSchema.overrides.json +674 -0
- package/api-types/storeApiTypes.d.ts +8512 -0
- package/api-types/storeApiTypes.overrides.ts +182 -0
- package/dist/index.cjs +170 -104
- package/dist/index.d.cts +89259 -62605
- package/dist/index.d.mts +89259 -62605
- package/dist/index.d.ts +89259 -62605
- package/dist/index.mjs +166 -104
- package/package.json +20 -14
- package/admin-api-types/apiTypes-6.5.3.0.d.ts +0 -59568
- package/admin-api-types/index.d.ts +0 -1
- package/api-types/apiSchema-6.4.20.0.json +0 -13830
- package/api-types/apiSchema-6.5.0.0.json +0 -16669
- package/api-types/apiSchema-6.5.2.0.json +0 -12154
- package/api-types/apiSchema-6.5.3.0.json +0 -12154
- package/api-types/apiTypes-6.4.19.0.d.ts +0 -8170
- package/api-types/apiTypes-6.4.20.0.d.ts +0 -8168
- package/api-types/apiTypes-6.5.0.0.d.ts +0 -7244
- package/api-types/apiTypes-6.5.2.0.d.ts +0 -7738
- package/api-types/apiTypes-6.5.3.0.d.ts +0 -7738
- package/api-types/index.d.ts +0 -1
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { components as mainComponents } from "./storeApiTypes";
|
|
2
|
+
|
|
3
|
+
export type components = mainComponents;
|
|
4
|
+
// & {
|
|
5
|
+
// schemas: schemas;
|
|
6
|
+
// };
|
|
7
|
+
|
|
8
|
+
export type Schemas = {
|
|
9
|
+
ProductListingResult: components["schemas"]["EntitySearchResult"] & {
|
|
10
|
+
/** @enum {string} */
|
|
11
|
+
apiAlias: "product_listing";
|
|
12
|
+
/** Contains the available sorting. These can be used to show a sorting select-box in the product listing. */
|
|
13
|
+
availableSortings: {
|
|
14
|
+
/** @enum {string} */
|
|
15
|
+
apiAlias: "product_sorting";
|
|
16
|
+
key: string;
|
|
17
|
+
label: string;
|
|
18
|
+
priority: number;
|
|
19
|
+
translated: {
|
|
20
|
+
apiAlias?: string;
|
|
21
|
+
key?: string;
|
|
22
|
+
label: string;
|
|
23
|
+
};
|
|
24
|
+
}[];
|
|
25
|
+
/** Contains the state of the filters. These can be used to create listing filters. */
|
|
26
|
+
currentFilters: {
|
|
27
|
+
manufacturer: string[];
|
|
28
|
+
navigationId: string;
|
|
29
|
+
price: {
|
|
30
|
+
/** @default 0 */
|
|
31
|
+
max: number;
|
|
32
|
+
/** @default 0 */
|
|
33
|
+
min: number;
|
|
34
|
+
};
|
|
35
|
+
properties: string[];
|
|
36
|
+
rating?: number; // TODO: [OpenAPI][ProductListingResult] - rating should be defined the same as in body of the request
|
|
37
|
+
search: string; // TODO: [OpenAPI][ProductListingResult] - search should be required as is required in body of the request, otherwise everywhere optional
|
|
38
|
+
/** @default false */
|
|
39
|
+
"shipping-free": boolean;
|
|
40
|
+
};
|
|
41
|
+
elements: components["schemas"]["Product"][];
|
|
42
|
+
/** @enum {string} */
|
|
43
|
+
entity?: "product";
|
|
44
|
+
sorting?: string;
|
|
45
|
+
};
|
|
46
|
+
SwagPaypalVaultToken: {
|
|
47
|
+
// TODO: [OpenAPI][SwagPaypalVaultToken] - add SwagPaypalVaultToken definition to schema
|
|
48
|
+
/** Format: date-time */
|
|
49
|
+
createdAt: string;
|
|
50
|
+
customer?: components["schemas"]["Customer"];
|
|
51
|
+
customerId: string;
|
|
52
|
+
id?: string;
|
|
53
|
+
identifier: string;
|
|
54
|
+
mainMapping?: components["schemas"]["SwagPaypalVaultTokenMapping"];
|
|
55
|
+
paymentMethod?: components["schemas"]["PaymentMethod"];
|
|
56
|
+
paymentMethodId: string;
|
|
57
|
+
/** Format: date-time */
|
|
58
|
+
updatedAt?: string;
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export type operations = {
|
|
63
|
+
"register post /account/register": {
|
|
64
|
+
contentType?: "application/json";
|
|
65
|
+
accept?: "application/json";
|
|
66
|
+
body: {
|
|
67
|
+
/** Flag indicating accepted data protection */
|
|
68
|
+
acceptedDataProtection: boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Account type of the customer which can be either `private` or `business`.
|
|
71
|
+
* @default private
|
|
72
|
+
*/
|
|
73
|
+
accountType?: string;
|
|
74
|
+
/** Field can be used to store an affiliate tracking code */
|
|
75
|
+
affiliateCode?: string;
|
|
76
|
+
billingAddress: Omit<
|
|
77
|
+
components["schemas"]["CustomerAddress"],
|
|
78
|
+
"createdAt" | "id" | "customerId" | "firstName" | "lastName"
|
|
79
|
+
>; // TODO: [OpenAPI][register] - omit id, createdAt, customerId, firstName, lastName while creating address (or better to reverse and pick required fields)
|
|
80
|
+
/** Birthday day */
|
|
81
|
+
birthdayDay?: number;
|
|
82
|
+
/** Birthday month */
|
|
83
|
+
birthdayMonth?: number;
|
|
84
|
+
/** Birthday year */
|
|
85
|
+
birthdayYear?: number;
|
|
86
|
+
/** Field can be used to store a campaign tracking code */
|
|
87
|
+
campaignCode?: string;
|
|
88
|
+
/** Email of the customer. Has to be unique, unless `guest` is `true` */
|
|
89
|
+
email: string;
|
|
90
|
+
/** Customer first name. Value will be reused for shipping and billing address if not provided explicitly. */
|
|
91
|
+
firstName: string;
|
|
92
|
+
/**
|
|
93
|
+
* If set, will create a guest customer. Guest customers can re-use an email address and don't need a password.
|
|
94
|
+
* @default false
|
|
95
|
+
*/
|
|
96
|
+
guest?: boolean;
|
|
97
|
+
/** Customer last name. Value will be reused for shipping and billing address if not provided explicitly. */
|
|
98
|
+
lastName: string;
|
|
99
|
+
/** Password for the customer. Required, unless `guest` is `true` */
|
|
100
|
+
password: string;
|
|
101
|
+
/** Id of the salutation for the customer account. Fetch options using `salutation` endpoint. */
|
|
102
|
+
salutationId: string;
|
|
103
|
+
shippingAddress?: components["schemas"]["CustomerAddress"];
|
|
104
|
+
/** URL of the storefront for that registration. Used in confirmation emails. Has to be one of the configured domains of the sales channel. */
|
|
105
|
+
storefrontUrl: string;
|
|
106
|
+
/** (Academic) title of the customer */
|
|
107
|
+
title?: string;
|
|
108
|
+
};
|
|
109
|
+
response: components["schemas"]["Customer"];
|
|
110
|
+
responseCode: 200;
|
|
111
|
+
};
|
|
112
|
+
"addLineItem post /checkout/cart/line-item": {
|
|
113
|
+
contentType?: "application/json";
|
|
114
|
+
accept?: "application/json";
|
|
115
|
+
headers?: {
|
|
116
|
+
/** Instructs Shopware to return the response in the given language. */
|
|
117
|
+
"sw-language-id"?: string;
|
|
118
|
+
};
|
|
119
|
+
body: {
|
|
120
|
+
// TODO: [OpenAPI][addLineItem] - add proper request body type with required fields
|
|
121
|
+
items: Array<{
|
|
122
|
+
id?: string; // TODO: [OpenAPI][addLineItem] - check if this is used at all?
|
|
123
|
+
referencedId: string;
|
|
124
|
+
quantity?: number;
|
|
125
|
+
type: "product" | "promotion" | "custom" | "credit"; // TODO: [OpenAPI][addLineItem] - add proper type -> see also #456
|
|
126
|
+
}>;
|
|
127
|
+
};
|
|
128
|
+
response: components["schemas"]["Cart"];
|
|
129
|
+
responseCode: 200;
|
|
130
|
+
};
|
|
131
|
+
"updateLineItem patch /checkout/cart/line-item": {
|
|
132
|
+
contentType?: "application/json";
|
|
133
|
+
accept?: "application/json";
|
|
134
|
+
headers?: {
|
|
135
|
+
/** Instructs Shopware to return the response in the given language. */
|
|
136
|
+
"sw-language-id"?: string;
|
|
137
|
+
};
|
|
138
|
+
body: {
|
|
139
|
+
// TODO: [OpenAPI][updateLineItem] - add proper request body type with required fields
|
|
140
|
+
items: Array<{
|
|
141
|
+
id: string;
|
|
142
|
+
quantity: number;
|
|
143
|
+
}>;
|
|
144
|
+
};
|
|
145
|
+
response: components["schemas"]["Cart"];
|
|
146
|
+
responseCode: 200;
|
|
147
|
+
};
|
|
148
|
+
"readProduct post /product": {
|
|
149
|
+
contentType?: "application/json";
|
|
150
|
+
accept?: "application/json";
|
|
151
|
+
headers?: {
|
|
152
|
+
/** Instructs Shopware to return the response in the given language. */
|
|
153
|
+
"sw-language-id"?: string;
|
|
154
|
+
};
|
|
155
|
+
body?: components["schemas"]["Criteria"];
|
|
156
|
+
response: {
|
|
157
|
+
elements: components["schemas"]["Product"][]; // TODO: [OpenAPI][readProduct]: add elements property as required
|
|
158
|
+
} & components["schemas"]["EntitySearchResult"];
|
|
159
|
+
responseCode: 200;
|
|
160
|
+
};
|
|
161
|
+
"readShippingMethod post /shipping-method": {
|
|
162
|
+
contentType?: "application/json";
|
|
163
|
+
accept?: "application/json";
|
|
164
|
+
headers?: {
|
|
165
|
+
/** Instructs Shopware to return the response in the given language. */
|
|
166
|
+
"sw-language-id"?: string;
|
|
167
|
+
};
|
|
168
|
+
query?: {
|
|
169
|
+
/** List only available shipping methods. This filters shipping methods methods which can not be used in the actual context because of their availability rule. */
|
|
170
|
+
onlyAvailable?: boolean;
|
|
171
|
+
};
|
|
172
|
+
body?: components["schemas"]["Criteria"];
|
|
173
|
+
response: {
|
|
174
|
+
/** aggregation result */
|
|
175
|
+
aggregations?: Record<string, never>;
|
|
176
|
+
elements: components["schemas"]["ShippingMethod"][]; // TODO: [OpenAPI][readShippingMethod]: response should be `EntitySearchResult` and elements should be required
|
|
177
|
+
/** Total amount */
|
|
178
|
+
total?: number;
|
|
179
|
+
};
|
|
180
|
+
responseCode: 200;
|
|
181
|
+
};
|
|
182
|
+
};
|
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,47 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const ofetch = require('ofetch');
|
|
4
|
+
const hookable = require('hookable');
|
|
5
|
+
const defu = require('defu');
|
|
6
|
+
|
|
7
|
+
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
|
|
8
|
+
|
|
9
|
+
const defu__default = /*#__PURE__*/_interopDefaultCompat(defu);
|
|
10
|
+
|
|
11
|
+
function createHeaders(init) {
|
|
12
|
+
const _headers = {
|
|
13
|
+
"Content-Type": "application/json"
|
|
14
|
+
};
|
|
15
|
+
const handler = {
|
|
16
|
+
get: (target, prop) => {
|
|
17
|
+
if (prop === "apply") {
|
|
18
|
+
return apply;
|
|
19
|
+
}
|
|
20
|
+
return Reflect.get(target, prop);
|
|
21
|
+
},
|
|
22
|
+
set: (target, prop, value) => {
|
|
23
|
+
if (prop === "apply") {
|
|
24
|
+
throw new Error("Cannot override apply method");
|
|
25
|
+
}
|
|
26
|
+
return Reflect.set(target, prop, value);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
const headersProxy = new Proxy(
|
|
30
|
+
_headers,
|
|
31
|
+
handler
|
|
32
|
+
);
|
|
33
|
+
function apply(headers) {
|
|
34
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
35
|
+
if (value) {
|
|
36
|
+
headersProxy[key] = value;
|
|
37
|
+
} else {
|
|
38
|
+
delete headersProxy[key];
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
headersProxy.apply({ ...init });
|
|
43
|
+
return headersProxy;
|
|
44
|
+
}
|
|
4
45
|
|
|
5
46
|
var __defProp = Object.defineProperty;
|
|
6
47
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
@@ -11,14 +52,23 @@ var __publicField = (obj, key, value) => {
|
|
|
11
52
|
class ApiClientError extends Error {
|
|
12
53
|
constructor(response) {
|
|
13
54
|
let message = "Failed request";
|
|
14
|
-
|
|
55
|
+
const errorDetails = response._data || {
|
|
56
|
+
errors: [
|
|
57
|
+
{
|
|
58
|
+
title: "Unknown error",
|
|
59
|
+
detail: "API did not return errors, but request failed. Please check the network tab."
|
|
60
|
+
}
|
|
61
|
+
]
|
|
62
|
+
};
|
|
63
|
+
message += errorDetails.errors?.reduce((message2, error) => {
|
|
15
64
|
let pointer = "";
|
|
16
65
|
if (error.source?.pointer) {
|
|
17
66
|
pointer = `[${error.source.pointer}]`;
|
|
18
67
|
}
|
|
68
|
+
const details = error.detail ?? "No error details provided.";
|
|
19
69
|
return `${message2}
|
|
20
|
-
- [${error.title}]${pointer} ${
|
|
21
|
-
}, "");
|
|
70
|
+
- [${error.title}]${pointer} ${details}`;
|
|
71
|
+
}, "") ?? "";
|
|
22
72
|
super(message);
|
|
23
73
|
/**
|
|
24
74
|
* Flag to indicate if the request was successful.
|
|
@@ -45,9 +95,7 @@ class ApiClientError extends Error {
|
|
|
45
95
|
*/
|
|
46
96
|
__publicField(this, "headers");
|
|
47
97
|
this.name = "ApiClientError";
|
|
48
|
-
this.details =
|
|
49
|
-
errors: [{ title: "Unknown error", detail: "" }]
|
|
50
|
-
};
|
|
98
|
+
this.details = errorDetails;
|
|
51
99
|
this.ok = response.ok;
|
|
52
100
|
this.status = response.status;
|
|
53
101
|
this.statusText = response.statusText;
|
|
@@ -55,185 +103,203 @@ class ApiClientError extends Error {
|
|
|
55
103
|
this.headers = response.headers;
|
|
56
104
|
}
|
|
57
105
|
}
|
|
106
|
+
|
|
58
107
|
function errorInterceptor(response) {
|
|
59
108
|
throw new ApiClientError(response);
|
|
60
109
|
}
|
|
61
110
|
|
|
62
|
-
function
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const pathParams = requestPath.match(/{[^}]+}/g)?.map((param) => param.substring(1, param.length - 1)) || [];
|
|
66
|
-
const requestPathWithParams = pathParams.reduce((acc, paramName) => {
|
|
67
|
-
return acc.replace(`{${paramName}}`, params[paramName]);
|
|
111
|
+
function createPathWithParams(requestPath, pathParams) {
|
|
112
|
+
return Object.keys(pathParams || {}).reduce((acc, paramName) => {
|
|
113
|
+
return acc.replace(`{${paramName}}`, pathParams[paramName]);
|
|
68
114
|
}, requestPath);
|
|
69
|
-
const queryParamNames = queryParams?.split(",") || [];
|
|
70
|
-
const headerParamnames = headerParams?.split(",") || [];
|
|
71
|
-
const headers = {};
|
|
72
|
-
headerParamnames.forEach((paramName) => {
|
|
73
|
-
headers[paramName] = params[paramName];
|
|
74
|
-
});
|
|
75
|
-
const query = {};
|
|
76
|
-
queryParamNames.forEach((paramName) => {
|
|
77
|
-
let queryParamName = paramName;
|
|
78
|
-
if (Array.isArray(params[paramName]) && !queryParamName.includes("[]")) {
|
|
79
|
-
queryParamName += "[]";
|
|
80
|
-
}
|
|
81
|
-
query[queryParamName] = params[paramName];
|
|
82
|
-
});
|
|
83
|
-
const returnOptions = {
|
|
84
|
-
method: method.toUpperCase(),
|
|
85
|
-
headers,
|
|
86
|
-
query
|
|
87
|
-
};
|
|
88
|
-
Object.keys(params).forEach((key) => {
|
|
89
|
-
if (!pathParams.includes(key) && !queryParamNames.includes(key) && !headerParamnames.includes(key)) {
|
|
90
|
-
returnOptions.body ?? (returnOptions.body = {});
|
|
91
|
-
Reflect.set(returnOptions.body, key, params[key]);
|
|
92
|
-
}
|
|
93
|
-
});
|
|
94
|
-
return [requestPathWithParams, returnOptions];
|
|
95
115
|
}
|
|
96
116
|
|
|
97
117
|
function createAPIClient(params) {
|
|
98
|
-
const defaultHeaders = {
|
|
99
|
-
"sw-access-key": params.accessToken
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
118
|
+
const defaultHeaders = createHeaders({
|
|
119
|
+
"sw-access-key": params.accessToken,
|
|
120
|
+
Accept: "application/json",
|
|
121
|
+
"sw-context-token": params.contextToken,
|
|
122
|
+
...params.defaultHeaders
|
|
123
|
+
});
|
|
124
|
+
const apiClientHooks = hookable.createHooks();
|
|
104
125
|
const apiFetch = ofetch.ofetch.create({
|
|
105
126
|
baseURL: params.baseURL,
|
|
106
127
|
// async onRequest({ request, options }) {},
|
|
107
128
|
// async onRequestError({ request, options, error }) {},
|
|
108
129
|
async onResponse(context) {
|
|
109
|
-
|
|
110
|
-
|
|
130
|
+
apiClientHooks.callHook("onSuccessResponse", context.response);
|
|
131
|
+
if (context.response.headers.has("sw-context-token") && defaultHeaders["sw-context-token"] !== context.response.headers.get("sw-context-token")) {
|
|
132
|
+
const newContextToken = context.response.headers.get(
|
|
133
|
+
"sw-context-token"
|
|
134
|
+
);
|
|
111
135
|
defaultHeaders["sw-context-token"] = newContextToken;
|
|
112
|
-
|
|
136
|
+
apiClientHooks.callHook("onContextChanged", newContextToken);
|
|
113
137
|
}
|
|
114
138
|
},
|
|
115
|
-
async onResponseError({
|
|
139
|
+
async onResponseError({ response }) {
|
|
140
|
+
apiClientHooks.callHook("onResponseError", response);
|
|
116
141
|
errorInterceptor(response);
|
|
117
142
|
}
|
|
118
143
|
});
|
|
119
|
-
async function invoke(pathParam, params2) {
|
|
120
|
-
const [
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
);
|
|
124
|
-
return apiFetch(
|
|
144
|
+
async function invoke(pathParam, ...params2) {
|
|
145
|
+
const [, method, requestPath] = pathParam.split(" ");
|
|
146
|
+
const currentParams = params2[0] || {};
|
|
147
|
+
const requestPathWithParams = createPathWithParams(
|
|
125
148
|
requestPath,
|
|
126
|
-
|
|
127
|
-
...options,
|
|
128
|
-
headers: {
|
|
129
|
-
...defaultHeaders,
|
|
130
|
-
...options.headers
|
|
131
|
-
}
|
|
132
|
-
}
|
|
149
|
+
currentParams.pathParams
|
|
133
150
|
);
|
|
151
|
+
const fetchOptions = {
|
|
152
|
+
...currentParams.fetchOptions || {}
|
|
153
|
+
};
|
|
154
|
+
const resp = await apiFetch.raw(requestPathWithParams, {
|
|
155
|
+
...fetchOptions,
|
|
156
|
+
method,
|
|
157
|
+
body: currentParams.body,
|
|
158
|
+
headers: defu__default(defaultHeaders, currentParams.headers),
|
|
159
|
+
query: currentParams.query
|
|
160
|
+
});
|
|
161
|
+
return {
|
|
162
|
+
data: resp._data,
|
|
163
|
+
status: resp.status
|
|
164
|
+
};
|
|
134
165
|
}
|
|
135
166
|
return {
|
|
136
|
-
invoke
|
|
167
|
+
invoke,
|
|
168
|
+
/**
|
|
169
|
+
* Default headers used in every client request (if not overriden in specific request).
|
|
170
|
+
*/
|
|
171
|
+
defaultHeaders,
|
|
172
|
+
hook: apiClientHooks.hook
|
|
137
173
|
};
|
|
138
174
|
}
|
|
175
|
+
|
|
139
176
|
function createAuthorizationHeader(token) {
|
|
140
177
|
if (!token)
|
|
141
|
-
return
|
|
178
|
+
return "";
|
|
142
179
|
if (token.startsWith("Bearer "))
|
|
143
180
|
return token;
|
|
144
181
|
return `Bearer ${token}`;
|
|
145
182
|
}
|
|
146
183
|
function createAdminAPIClient(params) {
|
|
184
|
+
const isTokenBasedAuth = params.credentials?.grant_type === "client_credentials";
|
|
147
185
|
const sessionData = {
|
|
148
186
|
accessToken: params.sessionData?.accessToken || "",
|
|
149
187
|
refreshToken: params.sessionData?.refreshToken || "",
|
|
150
188
|
expirationTime: Number(params.sessionData?.expirationTime || 0)
|
|
151
189
|
};
|
|
190
|
+
const defaultHeaders = createHeaders({
|
|
191
|
+
Authorization: createAuthorizationHeader(sessionData.accessToken),
|
|
192
|
+
Accept: "application/json"
|
|
193
|
+
});
|
|
194
|
+
const apiClientHooks = hookable.createHooks();
|
|
195
|
+
function getSessionData() {
|
|
196
|
+
return { ...sessionData };
|
|
197
|
+
}
|
|
198
|
+
function setSessionData(data) {
|
|
199
|
+
sessionData.accessToken = data.accessToken;
|
|
200
|
+
sessionData.refreshToken = data.refreshToken || "";
|
|
201
|
+
sessionData.expirationTime = data.expirationTime;
|
|
202
|
+
return getSessionData();
|
|
203
|
+
}
|
|
152
204
|
function updateSessionData(responseData) {
|
|
153
205
|
if (responseData?.access_token) {
|
|
154
206
|
defaultHeaders.Authorization = createAuthorizationHeader(
|
|
155
207
|
responseData.access_token
|
|
156
208
|
);
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
...sessionData
|
|
209
|
+
const dataCopy = setSessionData({
|
|
210
|
+
accessToken: responseData.access_token,
|
|
211
|
+
refreshToken: responseData.refresh_token,
|
|
212
|
+
expirationTime: Date.now() + responseData.expires_in * 1e3
|
|
162
213
|
});
|
|
214
|
+
apiClientHooks.callHook("onAuthChange", dataCopy);
|
|
163
215
|
}
|
|
164
216
|
}
|
|
165
|
-
function setSessionData(data) {
|
|
166
|
-
sessionData.accessToken = data.accessToken;
|
|
167
|
-
sessionData.refreshToken = data.refreshToken;
|
|
168
|
-
sessionData.expirationTime = data.expirationTime;
|
|
169
|
-
return getSessionData();
|
|
170
|
-
}
|
|
171
|
-
function getSessionData() {
|
|
172
|
-
return { ...sessionData };
|
|
173
|
-
}
|
|
174
|
-
const defaultHeaders = {
|
|
175
|
-
Authorization: createAuthorizationHeader(sessionData.accessToken)
|
|
176
|
-
};
|
|
177
217
|
const apiFetch = ofetch.ofetch.create({
|
|
178
218
|
baseURL: params.baseURL,
|
|
179
219
|
async onRequest({ request, options }) {
|
|
180
220
|
const isExpired = sessionData.expirationTime <= Date.now();
|
|
181
221
|
if (isExpired && !request.toString().includes("/oauth/token")) {
|
|
222
|
+
if (!params.credentials && !isTokenBasedAuth && !sessionData.refreshToken) {
|
|
223
|
+
console.warn(
|
|
224
|
+
"[ApiClientWarning] No `credentials` or `sessionData` provided. Provide at least one of them to ensure authentication."
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
const body = params.credentials && !sessionData.refreshToken ? params.credentials : {
|
|
228
|
+
grant_type: "refresh_token",
|
|
229
|
+
client_id: "administration",
|
|
230
|
+
refresh_token: sessionData.refreshToken
|
|
231
|
+
};
|
|
182
232
|
await ofetch.ofetch("/oauth/token", {
|
|
183
233
|
baseURL: params.baseURL,
|
|
184
234
|
method: "POST",
|
|
185
|
-
body
|
|
186
|
-
grant_type: "refresh_token",
|
|
187
|
-
client_id: "administration",
|
|
188
|
-
refresh_token: sessionData.refreshToken || ""
|
|
189
|
-
},
|
|
235
|
+
body,
|
|
190
236
|
headers: defaultHeaders,
|
|
191
237
|
onResponseError({ response }) {
|
|
192
238
|
errorInterceptor(response);
|
|
193
239
|
},
|
|
194
240
|
onResponse(context) {
|
|
241
|
+
if (!context.response._data)
|
|
242
|
+
return;
|
|
195
243
|
updateSessionData(context.response._data);
|
|
244
|
+
options.headers = {
|
|
245
|
+
...options.headers,
|
|
246
|
+
Authorization: createAuthorizationHeader(
|
|
247
|
+
context.response._data.access_token
|
|
248
|
+
)
|
|
249
|
+
};
|
|
196
250
|
}
|
|
197
251
|
});
|
|
198
252
|
}
|
|
199
253
|
},
|
|
200
254
|
async onResponse(context) {
|
|
255
|
+
apiClientHooks.callHook("onSuccessResponse", context.response);
|
|
201
256
|
updateSessionData(context.response._data);
|
|
202
257
|
},
|
|
203
|
-
async onResponseError({
|
|
258
|
+
async onResponseError({ response }) {
|
|
259
|
+
apiClientHooks.callHook("onResponseError", response);
|
|
204
260
|
errorInterceptor(response);
|
|
205
261
|
}
|
|
206
262
|
});
|
|
207
|
-
async function invoke(pathParam, params2) {
|
|
208
|
-
const [
|
|
209
|
-
|
|
210
|
-
params2
|
|
211
|
-
);
|
|
212
|
-
return apiFetch(
|
|
263
|
+
async function invoke(pathParam, ...params2) {
|
|
264
|
+
const [, method, requestPath] = pathParam.split(" ");
|
|
265
|
+
const requestPathWithParams = createPathWithParams(
|
|
213
266
|
requestPath,
|
|
214
|
-
|
|
215
|
-
...options,
|
|
216
|
-
headers: {
|
|
217
|
-
...defaultHeaders,
|
|
218
|
-
...options.headers
|
|
219
|
-
}
|
|
220
|
-
}
|
|
267
|
+
params2[0]?.pathParams
|
|
221
268
|
);
|
|
269
|
+
const fetchOptions = {
|
|
270
|
+
...params2[0]?.fetchOptions || {}
|
|
271
|
+
};
|
|
272
|
+
const resp = await apiFetch.raw(requestPathWithParams, {
|
|
273
|
+
...fetchOptions,
|
|
274
|
+
method,
|
|
275
|
+
body: params2[0]?.body,
|
|
276
|
+
headers: defu__default(defaultHeaders, params2[0]?.headers),
|
|
277
|
+
query: params2[0]?.query
|
|
278
|
+
});
|
|
279
|
+
return {
|
|
280
|
+
data: resp._data,
|
|
281
|
+
status: resp.status
|
|
282
|
+
};
|
|
222
283
|
}
|
|
223
284
|
return {
|
|
224
|
-
/**
|
|
225
|
-
* Invoke API request based on provided path definition.
|
|
226
|
-
*/
|
|
227
285
|
invoke,
|
|
228
286
|
/**
|
|
229
287
|
* Enables to change session data in runtime. Useful for testing purposes.
|
|
230
|
-
* Setting session data with this
|
|
288
|
+
* Setting session data with this method will **not** fire `onAuthChange` hook.
|
|
231
289
|
*/
|
|
232
290
|
setSessionData,
|
|
233
291
|
/**
|
|
234
292
|
* Returns current session data. Useful for testing purposes, as in most cases you'll want to use `onAuthChange` hook for that.
|
|
235
293
|
*/
|
|
236
|
-
getSessionData
|
|
294
|
+
getSessionData,
|
|
295
|
+
/**
|
|
296
|
+
* Default headers used in every client request (if not overriden in specific request).
|
|
297
|
+
*/
|
|
298
|
+
defaultHeaders,
|
|
299
|
+
/**
|
|
300
|
+
* Available hooks for the client.
|
|
301
|
+
*/
|
|
302
|
+
hook: apiClientHooks.hook
|
|
237
303
|
};
|
|
238
304
|
}
|
|
239
305
|
|