@vulog/aima-client 1.0.7 → 1.0.9
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.d.mts +12 -1
- package/dist/index.d.ts +12 -1
- package/dist/index.js +93 -1
- package/dist/index.mjs +93 -1
- package/package.json +1 -1
- package/src/CurlHelper.ts +108 -0
- package/src/getClient.ts +22 -1
- package/src/index.ts +2 -2
- package/src/types.ts +4 -0
package/dist/index.d.mts
CHANGED
|
@@ -9,6 +9,17 @@ type ClientOptions = {
|
|
|
9
9
|
clientSecret: string;
|
|
10
10
|
apiKey: string;
|
|
11
11
|
secure?: boolean;
|
|
12
|
+
logCurl?: boolean;
|
|
13
|
+
logResponse?: boolean;
|
|
14
|
+
onRefreshToken?: (refreshToken: string) => void;
|
|
15
|
+
onLog?: (...args: any[]) => void;
|
|
16
|
+
};
|
|
17
|
+
type ClientError = {
|
|
18
|
+
formattedError: {
|
|
19
|
+
status: number;
|
|
20
|
+
data: any;
|
|
21
|
+
};
|
|
22
|
+
originalError: any;
|
|
12
23
|
};
|
|
13
24
|
type Client = AxiosInstance & {
|
|
14
25
|
refreshToken?: string;
|
|
@@ -17,4 +28,4 @@ type Client = AxiosInstance & {
|
|
|
17
28
|
|
|
18
29
|
declare const getClient: (options: ClientOptions) => Client;
|
|
19
30
|
|
|
20
|
-
export { type ClientOptions, getClient };
|
|
31
|
+
export { type Client, type ClientError, type ClientOptions, getClient };
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,17 @@ type ClientOptions = {
|
|
|
9
9
|
clientSecret: string;
|
|
10
10
|
apiKey: string;
|
|
11
11
|
secure?: boolean;
|
|
12
|
+
logCurl?: boolean;
|
|
13
|
+
logResponse?: boolean;
|
|
14
|
+
onRefreshToken?: (refreshToken: string) => void;
|
|
15
|
+
onLog?: (...args: any[]) => void;
|
|
16
|
+
};
|
|
17
|
+
type ClientError = {
|
|
18
|
+
formattedError: {
|
|
19
|
+
status: number;
|
|
20
|
+
data: any;
|
|
21
|
+
};
|
|
22
|
+
originalError: any;
|
|
12
23
|
};
|
|
13
24
|
type Client = AxiosInstance & {
|
|
14
25
|
refreshToken?: string;
|
|
@@ -17,4 +28,4 @@ type Client = AxiosInstance & {
|
|
|
17
28
|
|
|
18
29
|
declare const getClient: (options: ClientOptions) => Client;
|
|
19
30
|
|
|
20
|
-
export { type ClientOptions, getClient };
|
|
31
|
+
export { type Client, type ClientError, type ClientOptions, getClient };
|
package/dist/index.js
CHANGED
|
@@ -38,6 +38,81 @@ module.exports = __toCommonJS(src_exports);
|
|
|
38
38
|
var import_axios = __toESM(require("axios"));
|
|
39
39
|
var import_lodash = __toESM(require("lodash"));
|
|
40
40
|
var import_lru_cache = require("lru-cache");
|
|
41
|
+
|
|
42
|
+
// src/CurlHelper.ts
|
|
43
|
+
var CurlHelper = class {
|
|
44
|
+
request;
|
|
45
|
+
constructor(config) {
|
|
46
|
+
this.request = config;
|
|
47
|
+
}
|
|
48
|
+
getHeaders() {
|
|
49
|
+
let { headers } = this.request;
|
|
50
|
+
let curlHeaders = "";
|
|
51
|
+
if (headers.hasOwnProperty("common")) {
|
|
52
|
+
headers = this.request.headers[this.request.method];
|
|
53
|
+
}
|
|
54
|
+
for (const property in this.request.headers) {
|
|
55
|
+
if (!["common", "delete", "get", "head", "patch", "post", "put"].includes(property)) {
|
|
56
|
+
headers[property] = this.request.headers[property];
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
for (const property in headers) {
|
|
60
|
+
if ({}.hasOwnProperty.call(headers, property)) {
|
|
61
|
+
const header = `${property}:${headers[property]}`;
|
|
62
|
+
curlHeaders = `${curlHeaders} -H '${header}'`;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return curlHeaders.trim();
|
|
66
|
+
}
|
|
67
|
+
getMethod() {
|
|
68
|
+
return `-X ${this.request.method.toUpperCase()}`;
|
|
69
|
+
}
|
|
70
|
+
getBody() {
|
|
71
|
+
if (typeof this.request.data !== "undefined" && this.request.data !== "" && this.request.data !== null && this.request.method.toUpperCase() !== "GET") {
|
|
72
|
+
const data = typeof this.request.data === "object" || Object.prototype.toString.call(this.request.data) === "[object Array]" ? JSON.stringify(this.request.data) : this.request.data;
|
|
73
|
+
return `--data '${data}'`.trim();
|
|
74
|
+
}
|
|
75
|
+
return "";
|
|
76
|
+
}
|
|
77
|
+
getUrl() {
|
|
78
|
+
if (this.request.baseURL) {
|
|
79
|
+
const baseUrl = this.request.baseURL;
|
|
80
|
+
const { url } = this.request;
|
|
81
|
+
const finalUrl = `${baseUrl}/${url}`;
|
|
82
|
+
return finalUrl.replace(/\/{2,}/g, "/").replace("http:/", "http://").replace("https:/", "https://");
|
|
83
|
+
}
|
|
84
|
+
return this.request.url;
|
|
85
|
+
}
|
|
86
|
+
getQueryString() {
|
|
87
|
+
if (this.request.paramsSerializer) {
|
|
88
|
+
const params2 = this.request.paramsSerializer(this.request.params);
|
|
89
|
+
if (!params2 || params2.length === 0) return "";
|
|
90
|
+
if (params2.startsWith("?")) return params2;
|
|
91
|
+
return `?${params2}`;
|
|
92
|
+
}
|
|
93
|
+
let params = "";
|
|
94
|
+
let i = 0;
|
|
95
|
+
for (const param in this.request.params) {
|
|
96
|
+
if ({}.hasOwnProperty.call(this.request.params, param)) {
|
|
97
|
+
params += i !== 0 ? `&${param}=${this.request.params[param]}` : `?${param}=${this.request.params[param]}`;
|
|
98
|
+
i += 1;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return params;
|
|
102
|
+
}
|
|
103
|
+
getBuiltURL() {
|
|
104
|
+
let url = this.getUrl();
|
|
105
|
+
if (this.getQueryString() !== "") {
|
|
106
|
+
url += this.getQueryString();
|
|
107
|
+
}
|
|
108
|
+
return url.trim();
|
|
109
|
+
}
|
|
110
|
+
generateCommand() {
|
|
111
|
+
return `curl ${this.getMethod()} "${this.getBuiltURL()}" ${this.getHeaders()} ${this.getBody()}`.trim().replace(/\s{2,}/g, " ");
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
// src/getClient.ts
|
|
41
116
|
var clientCache = new import_lru_cache.LRUCache({ max: 100 });
|
|
42
117
|
var formatError = (error) => {
|
|
43
118
|
const { response: { status, data } = { status: 500 } } = error ?? {};
|
|
@@ -109,6 +184,7 @@ var getClient = (options) => {
|
|
|
109
184
|
);
|
|
110
185
|
client.defaults.headers.Authorization = `Bearer ${token.access_token}`;
|
|
111
186
|
client.refreshToken = token.refresh_token;
|
|
187
|
+
options.onRefreshToken?.(token.refresh_token);
|
|
112
188
|
return token.access_token;
|
|
113
189
|
};
|
|
114
190
|
client.signInWithPassword = async (username, password) => {
|
|
@@ -136,8 +212,24 @@ var getClient = (options) => {
|
|
|
136
212
|
client.defaults.headers.Authorization = `Bearer ${token.access_token}`;
|
|
137
213
|
client.refreshToken = token.refresh_token;
|
|
138
214
|
};
|
|
215
|
+
if (options.logCurl) {
|
|
216
|
+
client.interceptors.request.use((request) => {
|
|
217
|
+
const curl = new CurlHelper(request).generateCommand();
|
|
218
|
+
if (options.onLog) options.onLog({ curl, message: "getClient > Curl command" });
|
|
219
|
+
else console.log({ curl, message: "getClient > Curl command" });
|
|
220
|
+
return request;
|
|
221
|
+
});
|
|
222
|
+
}
|
|
139
223
|
client.interceptors.response.use(
|
|
140
|
-
(response) =>
|
|
224
|
+
(response) => {
|
|
225
|
+
if (options.logResponse) {
|
|
226
|
+
const finalUrl = new CurlHelper(response.config).getBuiltURL();
|
|
227
|
+
const { data } = response;
|
|
228
|
+
if (options.onLog) options.onLog({ finalUrl, data, message: "getClient > Response" });
|
|
229
|
+
else console.log({ finalUrl, data, message: "getClient > Response" });
|
|
230
|
+
}
|
|
231
|
+
return response;
|
|
232
|
+
},
|
|
141
233
|
(error) => {
|
|
142
234
|
const { config, response: { status } = { status: 500 } } = error;
|
|
143
235
|
const originalRequest = config;
|
package/dist/index.mjs
CHANGED
|
@@ -2,6 +2,81 @@
|
|
|
2
2
|
import axios from "axios";
|
|
3
3
|
import _ from "lodash";
|
|
4
4
|
import { LRUCache } from "lru-cache";
|
|
5
|
+
|
|
6
|
+
// src/CurlHelper.ts
|
|
7
|
+
var CurlHelper = class {
|
|
8
|
+
request;
|
|
9
|
+
constructor(config) {
|
|
10
|
+
this.request = config;
|
|
11
|
+
}
|
|
12
|
+
getHeaders() {
|
|
13
|
+
let { headers } = this.request;
|
|
14
|
+
let curlHeaders = "";
|
|
15
|
+
if (headers.hasOwnProperty("common")) {
|
|
16
|
+
headers = this.request.headers[this.request.method];
|
|
17
|
+
}
|
|
18
|
+
for (const property in this.request.headers) {
|
|
19
|
+
if (!["common", "delete", "get", "head", "patch", "post", "put"].includes(property)) {
|
|
20
|
+
headers[property] = this.request.headers[property];
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
for (const property in headers) {
|
|
24
|
+
if ({}.hasOwnProperty.call(headers, property)) {
|
|
25
|
+
const header = `${property}:${headers[property]}`;
|
|
26
|
+
curlHeaders = `${curlHeaders} -H '${header}'`;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return curlHeaders.trim();
|
|
30
|
+
}
|
|
31
|
+
getMethod() {
|
|
32
|
+
return `-X ${this.request.method.toUpperCase()}`;
|
|
33
|
+
}
|
|
34
|
+
getBody() {
|
|
35
|
+
if (typeof this.request.data !== "undefined" && this.request.data !== "" && this.request.data !== null && this.request.method.toUpperCase() !== "GET") {
|
|
36
|
+
const data = typeof this.request.data === "object" || Object.prototype.toString.call(this.request.data) === "[object Array]" ? JSON.stringify(this.request.data) : this.request.data;
|
|
37
|
+
return `--data '${data}'`.trim();
|
|
38
|
+
}
|
|
39
|
+
return "";
|
|
40
|
+
}
|
|
41
|
+
getUrl() {
|
|
42
|
+
if (this.request.baseURL) {
|
|
43
|
+
const baseUrl = this.request.baseURL;
|
|
44
|
+
const { url } = this.request;
|
|
45
|
+
const finalUrl = `${baseUrl}/${url}`;
|
|
46
|
+
return finalUrl.replace(/\/{2,}/g, "/").replace("http:/", "http://").replace("https:/", "https://");
|
|
47
|
+
}
|
|
48
|
+
return this.request.url;
|
|
49
|
+
}
|
|
50
|
+
getQueryString() {
|
|
51
|
+
if (this.request.paramsSerializer) {
|
|
52
|
+
const params2 = this.request.paramsSerializer(this.request.params);
|
|
53
|
+
if (!params2 || params2.length === 0) return "";
|
|
54
|
+
if (params2.startsWith("?")) return params2;
|
|
55
|
+
return `?${params2}`;
|
|
56
|
+
}
|
|
57
|
+
let params = "";
|
|
58
|
+
let i = 0;
|
|
59
|
+
for (const param in this.request.params) {
|
|
60
|
+
if ({}.hasOwnProperty.call(this.request.params, param)) {
|
|
61
|
+
params += i !== 0 ? `&${param}=${this.request.params[param]}` : `?${param}=${this.request.params[param]}`;
|
|
62
|
+
i += 1;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return params;
|
|
66
|
+
}
|
|
67
|
+
getBuiltURL() {
|
|
68
|
+
let url = this.getUrl();
|
|
69
|
+
if (this.getQueryString() !== "") {
|
|
70
|
+
url += this.getQueryString();
|
|
71
|
+
}
|
|
72
|
+
return url.trim();
|
|
73
|
+
}
|
|
74
|
+
generateCommand() {
|
|
75
|
+
return `curl ${this.getMethod()} "${this.getBuiltURL()}" ${this.getHeaders()} ${this.getBody()}`.trim().replace(/\s{2,}/g, " ");
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// src/getClient.ts
|
|
5
80
|
var clientCache = new LRUCache({ max: 100 });
|
|
6
81
|
var formatError = (error) => {
|
|
7
82
|
const { response: { status, data } = { status: 500 } } = error ?? {};
|
|
@@ -73,6 +148,7 @@ var getClient = (options) => {
|
|
|
73
148
|
);
|
|
74
149
|
client.defaults.headers.Authorization = `Bearer ${token.access_token}`;
|
|
75
150
|
client.refreshToken = token.refresh_token;
|
|
151
|
+
options.onRefreshToken?.(token.refresh_token);
|
|
76
152
|
return token.access_token;
|
|
77
153
|
};
|
|
78
154
|
client.signInWithPassword = async (username, password) => {
|
|
@@ -100,8 +176,24 @@ var getClient = (options) => {
|
|
|
100
176
|
client.defaults.headers.Authorization = `Bearer ${token.access_token}`;
|
|
101
177
|
client.refreshToken = token.refresh_token;
|
|
102
178
|
};
|
|
179
|
+
if (options.logCurl) {
|
|
180
|
+
client.interceptors.request.use((request) => {
|
|
181
|
+
const curl = new CurlHelper(request).generateCommand();
|
|
182
|
+
if (options.onLog) options.onLog({ curl, message: "getClient > Curl command" });
|
|
183
|
+
else console.log({ curl, message: "getClient > Curl command" });
|
|
184
|
+
return request;
|
|
185
|
+
});
|
|
186
|
+
}
|
|
103
187
|
client.interceptors.response.use(
|
|
104
|
-
(response) =>
|
|
188
|
+
(response) => {
|
|
189
|
+
if (options.logResponse) {
|
|
190
|
+
const finalUrl = new CurlHelper(response.config).getBuiltURL();
|
|
191
|
+
const { data } = response;
|
|
192
|
+
if (options.onLog) options.onLog({ finalUrl, data, message: "getClient > Response" });
|
|
193
|
+
else console.log({ finalUrl, data, message: "getClient > Response" });
|
|
194
|
+
}
|
|
195
|
+
return response;
|
|
196
|
+
},
|
|
105
197
|
(error) => {
|
|
106
198
|
const { config, response: { status } = { status: 500 } } = error;
|
|
107
199
|
const originalRequest = config;
|
package/package.json
CHANGED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
export class CurlHelper {
|
|
2
|
+
private request: any;
|
|
3
|
+
|
|
4
|
+
constructor(config: any) {
|
|
5
|
+
this.request = config;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
getHeaders() {
|
|
9
|
+
let { headers } = this.request;
|
|
10
|
+
let curlHeaders = '';
|
|
11
|
+
|
|
12
|
+
// get the headers concerning the appropriate method (defined in the global axios instance)
|
|
13
|
+
// eslint-disable-next-line no-prototype-builtins
|
|
14
|
+
if (headers.hasOwnProperty('common')) {
|
|
15
|
+
headers = this.request.headers[this.request.method];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// add any custom headers (defined upon calling methods like .get(), .post(), etc.)
|
|
19
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
20
|
+
for (const property in this.request.headers) {
|
|
21
|
+
if (!['common', 'delete', 'get', 'head', 'patch', 'post', 'put'].includes(property)) {
|
|
22
|
+
headers[property] = this.request.headers[property];
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
27
|
+
for (const property in headers) {
|
|
28
|
+
if ({}.hasOwnProperty.call(headers, property)) {
|
|
29
|
+
const header = `${property}:${headers[property]}`;
|
|
30
|
+
curlHeaders = `${curlHeaders} -H '${header}'`;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return curlHeaders.trim();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
getMethod() {
|
|
38
|
+
return `-X ${this.request.method.toUpperCase()}`;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
getBody() {
|
|
42
|
+
if (
|
|
43
|
+
typeof this.request.data !== 'undefined' &&
|
|
44
|
+
this.request.data !== '' &&
|
|
45
|
+
this.request.data !== null &&
|
|
46
|
+
this.request.method.toUpperCase() !== 'GET'
|
|
47
|
+
) {
|
|
48
|
+
const data =
|
|
49
|
+
typeof this.request.data === 'object' ||
|
|
50
|
+
Object.prototype.toString.call(this.request.data) === '[object Array]'
|
|
51
|
+
? JSON.stringify(this.request.data)
|
|
52
|
+
: this.request.data;
|
|
53
|
+
return `--data '${data}'`.trim();
|
|
54
|
+
}
|
|
55
|
+
return '';
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
getUrl() {
|
|
59
|
+
if (this.request.baseURL) {
|
|
60
|
+
const baseUrl = this.request.baseURL;
|
|
61
|
+
const { url } = this.request;
|
|
62
|
+
const finalUrl = `${baseUrl}/${url}`;
|
|
63
|
+
return finalUrl
|
|
64
|
+
.replace(/\/{2,}/g, '/')
|
|
65
|
+
.replace('http:/', 'http://')
|
|
66
|
+
.replace('https:/', 'https://');
|
|
67
|
+
}
|
|
68
|
+
return this.request.url;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
getQueryString() {
|
|
72
|
+
if (this.request.paramsSerializer) {
|
|
73
|
+
const params = this.request.paramsSerializer(this.request.params);
|
|
74
|
+
if (!params || params.length === 0) return '';
|
|
75
|
+
if (params.startsWith('?')) return params;
|
|
76
|
+
return `?${params}`;
|
|
77
|
+
}
|
|
78
|
+
let params = '';
|
|
79
|
+
let i = 0;
|
|
80
|
+
|
|
81
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
82
|
+
for (const param in this.request.params) {
|
|
83
|
+
if ({}.hasOwnProperty.call(this.request.params, param)) {
|
|
84
|
+
params +=
|
|
85
|
+
i !== 0 ? `&${param}=${this.request.params[param]}` : `?${param}=${this.request.params[param]}`;
|
|
86
|
+
i += 1;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return params;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
getBuiltURL() {
|
|
94
|
+
let url = this.getUrl();
|
|
95
|
+
|
|
96
|
+
if (this.getQueryString() !== '') {
|
|
97
|
+
url += this.getQueryString();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return url.trim();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
generateCommand() {
|
|
104
|
+
return `curl ${this.getMethod()} "${this.getBuiltURL()}" ${this.getHeaders()} ${this.getBody()}`
|
|
105
|
+
.trim()
|
|
106
|
+
.replace(/\s{2,}/g, ' ');
|
|
107
|
+
}
|
|
108
|
+
}
|
package/src/getClient.ts
CHANGED
|
@@ -2,6 +2,7 @@ import axios from 'axios';
|
|
|
2
2
|
import _ from 'lodash';
|
|
3
3
|
import { LRUCache } from 'lru-cache';
|
|
4
4
|
|
|
5
|
+
import { CurlHelper } from './CurlHelper';
|
|
5
6
|
import { Client, ClientError, ClientOptions } from './types';
|
|
6
7
|
|
|
7
8
|
const clientCache = new LRUCache<
|
|
@@ -89,6 +90,7 @@ const getClient = (options: ClientOptions): Client => {
|
|
|
89
90
|
);
|
|
90
91
|
client.defaults.headers.Authorization = `Bearer ${token.access_token}`;
|
|
91
92
|
client.refreshToken = token.refresh_token;
|
|
93
|
+
options.onRefreshToken?.(token.refresh_token);
|
|
92
94
|
return token.access_token;
|
|
93
95
|
};
|
|
94
96
|
|
|
@@ -119,8 +121,27 @@ const getClient = (options: ClientOptions): Client => {
|
|
|
119
121
|
client.refreshToken = token.refresh_token;
|
|
120
122
|
};
|
|
121
123
|
|
|
124
|
+
if (options.logCurl) {
|
|
125
|
+
client.interceptors.request.use((request) => {
|
|
126
|
+
const curl = new CurlHelper(request).generateCommand();
|
|
127
|
+
if (options.onLog) options.onLog({ curl, message: 'getClient > Curl command' });
|
|
128
|
+
// eslint-disable-next-line no-console
|
|
129
|
+
else console.log({ curl, message: 'getClient > Curl command' });
|
|
130
|
+
return request;
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
122
134
|
client.interceptors.response.use(
|
|
123
|
-
(response) =>
|
|
135
|
+
(response) => {
|
|
136
|
+
if (options.logResponse) {
|
|
137
|
+
const finalUrl = new CurlHelper(response.config).getBuiltURL();
|
|
138
|
+
const { data } = response;
|
|
139
|
+
if (options.onLog) options.onLog({ finalUrl, data, message: 'getClient > Response' });
|
|
140
|
+
// eslint-disable-next-line no-console
|
|
141
|
+
else console.log({ finalUrl, data, message: 'getClient > Response' });
|
|
142
|
+
}
|
|
143
|
+
return response;
|
|
144
|
+
},
|
|
124
145
|
(error) => {
|
|
125
146
|
const { config, response: { status } = { status: 500 } } = error;
|
|
126
147
|
const originalRequest = config;
|
package/src/index.ts
CHANGED
package/src/types.ts
CHANGED
|
@@ -9,6 +9,10 @@ export type ClientOptions = {
|
|
|
9
9
|
clientSecret: string;
|
|
10
10
|
apiKey: string;
|
|
11
11
|
secure?: boolean;
|
|
12
|
+
logCurl?: boolean;
|
|
13
|
+
logResponse?: boolean;
|
|
14
|
+
onRefreshToken?: (refreshToken: string) => void;
|
|
15
|
+
onLog?: (...args: any[]) => void;
|
|
12
16
|
};
|
|
13
17
|
|
|
14
18
|
export type ClientError = {
|