abbot-http-client 0.0.1
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 +113 -0
- package/dist/index.cjs +384 -0
- package/dist/index.d.cts +43 -0
- package/dist/index.d.ts +43 -0
- package/dist/index.js +346 -0
- package/eslint.config.mjs +35 -0
- package/package.json +34 -0
package/README.md
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
|
|
2
|
+
# ABBOT-HTTP-CLIENT
|
|
3
|
+
|
|
4
|
+
This package will provide you an Axios-like experience with customized request and response interceptors. Right now, we only have 2 modified methods available, which are POST and GET, and 1 customized method, which is uploadFile.
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
Install abbot-http-client with npm
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install abbot-http-client
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Install abbot-http-client with yarn
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
yarn add abbot-http-client
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Run locally
|
|
24
|
+
|
|
25
|
+
Clone the project
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
git clone git@gitlabsvr.abbot.tech:module/abbot-http-client.git
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Go to the project directory
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
cd abbot-http-client
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Install dependencies with yarn
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
yarn
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Create locally packe link with yarn
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
yarn link
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Link this package to your project to test
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
cd ./your/project/path
|
|
53
|
+
|
|
54
|
+
yarn link abbot-http-client
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
## Usage and Examples
|
|
59
|
+
|
|
60
|
+
Create instance
|
|
61
|
+
```javascript
|
|
62
|
+
// config.js
|
|
63
|
+
// config.ts
|
|
64
|
+
import { create } from "abbot-http-client";
|
|
65
|
+
|
|
66
|
+
// you can use dotenv package in this file
|
|
67
|
+
|
|
68
|
+
const coreHttp = create({
|
|
69
|
+
axios: {
|
|
70
|
+
baseUrl: "", // your baseUrl
|
|
71
|
+
timeout: 5000,
|
|
72
|
+
},
|
|
73
|
+
app: {
|
|
74
|
+
timezone: "Asia/Bangkok", // your timezone
|
|
75
|
+
apiKey: "", // your API Key
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
export default coreHttp
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Use instance in Your class
|
|
83
|
+
```typescript
|
|
84
|
+
// restHandler.ts
|
|
85
|
+
import coreHttp from "./path/to/your/config.ts";
|
|
86
|
+
|
|
87
|
+
...
|
|
88
|
+
|
|
89
|
+
// get user credential from your store provider
|
|
90
|
+
// user object has to contain key and token
|
|
91
|
+
// key means encryption key
|
|
92
|
+
// token means authorization token (Bearer token)
|
|
93
|
+
// this uer object can be null
|
|
94
|
+
const { user } = getState()
|
|
95
|
+
|
|
96
|
+
try {
|
|
97
|
+
const response = await coreHttp.post<ResType>(user, url, parameter)
|
|
98
|
+
return response
|
|
99
|
+
} catch(err: any) {
|
|
100
|
+
// err will have type of AxiosError with response
|
|
101
|
+
console.error(err)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
...
|
|
105
|
+
```
|
|
106
|
+
## Deployment (not supported yet)
|
|
107
|
+
|
|
108
|
+
To publish this project to NPM run
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
npm run publish
|
|
112
|
+
```
|
|
113
|
+
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
catchError: () => catchError,
|
|
34
|
+
create: () => create
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(index_exports);
|
|
37
|
+
|
|
38
|
+
// src/catchError.ts
|
|
39
|
+
async function catchError(promise, errorToCatch) {
|
|
40
|
+
return promise.then((data) => [void 0, data]).catch((error) => {
|
|
41
|
+
if (errorToCatch === void 0) return [error];
|
|
42
|
+
if (errorToCatch.some((e) => error instanceof e)) return [error];
|
|
43
|
+
throw error;
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// src/http.ts
|
|
48
|
+
var import_axios2 = require("axios");
|
|
49
|
+
|
|
50
|
+
// src/encryption/secure.ts
|
|
51
|
+
var Secure = class {
|
|
52
|
+
static keySize = 16;
|
|
53
|
+
static a = 5;
|
|
54
|
+
static b = 9;
|
|
55
|
+
static char = "0123456789";
|
|
56
|
+
static createId = () => {
|
|
57
|
+
const keyId = Array(this.keySize).fill("").map(() => {
|
|
58
|
+
const value = Math.floor(Math.random() * 10);
|
|
59
|
+
return this.char[value];
|
|
60
|
+
});
|
|
61
|
+
return keyId.join("");
|
|
62
|
+
};
|
|
63
|
+
static createKey = (keyId) => {
|
|
64
|
+
const crKey = Array(this.keySize).fill("").map((_, i) => Number(this.a ** Number(keyId[i]) % this.b));
|
|
65
|
+
return crKey.join("");
|
|
66
|
+
};
|
|
67
|
+
static toBase64Length16 = (text) => {
|
|
68
|
+
if (text && text.length) {
|
|
69
|
+
const b64 = Buffer.from(encodeURI(text)).toString("base64");
|
|
70
|
+
return b64.substring(0, 16);
|
|
71
|
+
}
|
|
72
|
+
return "";
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
// src/encryption/cryp.ts
|
|
77
|
+
var import_crypto_ts = require("crypto-ts");
|
|
78
|
+
|
|
79
|
+
// src/encryption/es.ts
|
|
80
|
+
var ES = class {
|
|
81
|
+
static e(value) {
|
|
82
|
+
return Array.from(value).map((c) => c.charCodeAt(0)).reverse().map((e, i) => i % 2 === 0 ? e + 1 : e - 1).map((e, i) => i % 3 === 0 ? e * 2 : e);
|
|
83
|
+
}
|
|
84
|
+
static d(value) {
|
|
85
|
+
const result = value.map((e, i) => i % 3 === 0 ? Math.round(e / 2) : e).map((e, i) => i % 2 === 0 ? e - 1 : e + 1);
|
|
86
|
+
return String.fromCharCode.apply(null, result.reverse());
|
|
87
|
+
}
|
|
88
|
+
static a2b(value) {
|
|
89
|
+
const charactors = "abcdefghijklmnopqrstuvwxyz";
|
|
90
|
+
const randomChar = (max) => Math.floor(Math.random() * max);
|
|
91
|
+
const result = value.map(
|
|
92
|
+
(e, i) => `${String(e)}${i === value.length - 1 ? "" : charactors[randomChar(26)]}`
|
|
93
|
+
).join("");
|
|
94
|
+
return result;
|
|
95
|
+
}
|
|
96
|
+
static b2a(value) {
|
|
97
|
+
if (!value) return [];
|
|
98
|
+
const result = value.split(/[a-z]/);
|
|
99
|
+
return result.map((e) => Number(e));
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
// src/encryption/cryp.ts
|
|
104
|
+
var Cryp = class {
|
|
105
|
+
ivText;
|
|
106
|
+
key;
|
|
107
|
+
keyBuffer;
|
|
108
|
+
iv;
|
|
109
|
+
algConfig;
|
|
110
|
+
constructor(cryptProps) {
|
|
111
|
+
this.ivText = cryptProps.iv;
|
|
112
|
+
this.key = cryptProps.keyValue ? cryptProps.keyValue : ES.d(ES.b2a(getConfig().app?.apiKey));
|
|
113
|
+
this.keyBuffer = import_crypto_ts.enc.Utf8.parse(this.key);
|
|
114
|
+
this.iv = import_crypto_ts.enc.Utf8.parse(this.ivText);
|
|
115
|
+
this.algConfig = { mode: import_crypto_ts.mode.CBC, padding: import_crypto_ts.pad.PKCS7, iv: this.iv };
|
|
116
|
+
}
|
|
117
|
+
encrypt(textValue) {
|
|
118
|
+
if (!textValue) return "";
|
|
119
|
+
if (!textValue.length) return textValue;
|
|
120
|
+
const cipher = import_crypto_ts.AES.encrypt(textValue, this.keyBuffer, this.algConfig);
|
|
121
|
+
return cipher.toString();
|
|
122
|
+
}
|
|
123
|
+
decrypt(encryptedValue) {
|
|
124
|
+
try {
|
|
125
|
+
if (!encryptedValue || !encryptedValue.length) return null;
|
|
126
|
+
const decryptValue = import_crypto_ts.AES.decrypt(
|
|
127
|
+
encryptedValue,
|
|
128
|
+
this.keyBuffer,
|
|
129
|
+
this.algConfig
|
|
130
|
+
);
|
|
131
|
+
const decryptData = decryptValue.toString(import_crypto_ts.enc.Utf8);
|
|
132
|
+
const jsonData = JSON.parse(decryptData);
|
|
133
|
+
return jsonData;
|
|
134
|
+
} catch (err) {
|
|
135
|
+
console.error(err);
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
// src/config/axiosFn.ts
|
|
142
|
+
var import_axios = __toESM(require("axios"), 1);
|
|
143
|
+
function axiosConf(cfg2) {
|
|
144
|
+
const axiosObj = import_axios.default.create({
|
|
145
|
+
baseURL: cfg2.axios?.baseUrl,
|
|
146
|
+
headers: {
|
|
147
|
+
common: {
|
|
148
|
+
Accept: cfg2.axios?.headers?.accept,
|
|
149
|
+
"Accept-Language": cfg2.axios?.headers?.lang
|
|
150
|
+
},
|
|
151
|
+
post: {
|
|
152
|
+
"Content-Type": cfg2.axios?.headers?.post?.contentType
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
timeout: cfg2.axios?.timeout,
|
|
156
|
+
withCredentials: true
|
|
157
|
+
});
|
|
158
|
+
return axiosObj;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// src/http.ts
|
|
162
|
+
var CoreHttp = class {
|
|
163
|
+
config;
|
|
164
|
+
constructor(config) {
|
|
165
|
+
this.config = config;
|
|
166
|
+
}
|
|
167
|
+
createAxiosInstance(user) {
|
|
168
|
+
const axios2 = axiosConf(this.config);
|
|
169
|
+
const iv = Secure.createId();
|
|
170
|
+
const cryp = new Cryp({
|
|
171
|
+
iv,
|
|
172
|
+
keyValue: user.key
|
|
173
|
+
});
|
|
174
|
+
axios2.interceptors.request.use(
|
|
175
|
+
(config) => {
|
|
176
|
+
const req = { ...config };
|
|
177
|
+
if (config.method && config.method.toLowerCase() === "post") {
|
|
178
|
+
if (config.data) {
|
|
179
|
+
if (config.data instanceof FormData) {
|
|
180
|
+
if (config.data.get("param")) {
|
|
181
|
+
config.data.set(
|
|
182
|
+
"param",
|
|
183
|
+
cryp.encrypt(config.data.get("param")?.toString())
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
} else {
|
|
187
|
+
const payload = {};
|
|
188
|
+
payload.param = cryp.encrypt(JSON.stringify(config.data));
|
|
189
|
+
const body = payload ? new URLSearchParams(payload).toString() : "";
|
|
190
|
+
req.data = body;
|
|
191
|
+
req.headers.setContentType("application/x-www-form-urlencoded");
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
req.headers.set("data-code", iv);
|
|
196
|
+
if (user.token) {
|
|
197
|
+
req.headers.setAuthorization(`Bearer ${user.token}`);
|
|
198
|
+
}
|
|
199
|
+
return req;
|
|
200
|
+
},
|
|
201
|
+
(error) => Promise.reject(error)
|
|
202
|
+
);
|
|
203
|
+
axios2.interceptors.response.use(
|
|
204
|
+
(response) => {
|
|
205
|
+
const res = { ...response };
|
|
206
|
+
res.data = cryp.decrypt(response.data);
|
|
207
|
+
return res.data;
|
|
208
|
+
},
|
|
209
|
+
(error) => {
|
|
210
|
+
const err = {
|
|
211
|
+
message: error.message,
|
|
212
|
+
code: error.code,
|
|
213
|
+
config: error.config,
|
|
214
|
+
request: error.request
|
|
215
|
+
};
|
|
216
|
+
if (error.response) {
|
|
217
|
+
if (error.response.data) {
|
|
218
|
+
const response = cryp.decrypt(error.response.data);
|
|
219
|
+
err.response = response;
|
|
220
|
+
return Promise.reject(
|
|
221
|
+
new import_axios2.AxiosError(
|
|
222
|
+
err.message,
|
|
223
|
+
err.code,
|
|
224
|
+
err.config,
|
|
225
|
+
err.request,
|
|
226
|
+
err.response
|
|
227
|
+
)
|
|
228
|
+
);
|
|
229
|
+
} else {
|
|
230
|
+
err.response = {
|
|
231
|
+
status: "error",
|
|
232
|
+
code: error.response.status,
|
|
233
|
+
message: error.message,
|
|
234
|
+
data: null
|
|
235
|
+
};
|
|
236
|
+
return Promise.reject(
|
|
237
|
+
new import_axios2.AxiosError(
|
|
238
|
+
err.message,
|
|
239
|
+
err.code,
|
|
240
|
+
err.config,
|
|
241
|
+
err.request,
|
|
242
|
+
err.response
|
|
243
|
+
)
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
} else if (error.request) {
|
|
247
|
+
err.response = {
|
|
248
|
+
status: "error",
|
|
249
|
+
code: 0,
|
|
250
|
+
message: "No response received",
|
|
251
|
+
data: null
|
|
252
|
+
};
|
|
253
|
+
return Promise.reject(
|
|
254
|
+
new import_axios2.AxiosError(
|
|
255
|
+
err.message,
|
|
256
|
+
err.code,
|
|
257
|
+
err.config,
|
|
258
|
+
err.request,
|
|
259
|
+
err.response
|
|
260
|
+
)
|
|
261
|
+
);
|
|
262
|
+
} else {
|
|
263
|
+
err.response = {
|
|
264
|
+
status: "error",
|
|
265
|
+
code: 0,
|
|
266
|
+
message: error.message,
|
|
267
|
+
data: null
|
|
268
|
+
};
|
|
269
|
+
return Promise.reject(
|
|
270
|
+
new import_axios2.AxiosError(
|
|
271
|
+
err.message,
|
|
272
|
+
err.code,
|
|
273
|
+
err.config,
|
|
274
|
+
err.request,
|
|
275
|
+
err.response
|
|
276
|
+
)
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
);
|
|
281
|
+
return axios2;
|
|
282
|
+
}
|
|
283
|
+
async post(param1, url, param) {
|
|
284
|
+
let axios2;
|
|
285
|
+
if (typeof param1 === "function") {
|
|
286
|
+
const user = param1();
|
|
287
|
+
axios2 = this.createAxiosInstance({
|
|
288
|
+
key: user?.key,
|
|
289
|
+
token: user?.token
|
|
290
|
+
});
|
|
291
|
+
} else {
|
|
292
|
+
axios2 = this.createAxiosInstance({
|
|
293
|
+
key: param1?.key,
|
|
294
|
+
token: param1?.token
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
const response = await axios2.post(url, param);
|
|
298
|
+
return response;
|
|
299
|
+
}
|
|
300
|
+
async get(param1, url) {
|
|
301
|
+
let axios2;
|
|
302
|
+
if (typeof param1 === "function") {
|
|
303
|
+
const user = param1();
|
|
304
|
+
axios2 = this.createAxiosInstance({
|
|
305
|
+
key: user?.key,
|
|
306
|
+
token: user?.token
|
|
307
|
+
});
|
|
308
|
+
} else {
|
|
309
|
+
axios2 = this.createAxiosInstance({
|
|
310
|
+
key: param1?.key,
|
|
311
|
+
token: param1?.token
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
const response = await axios2.get(url);
|
|
315
|
+
return response;
|
|
316
|
+
}
|
|
317
|
+
async uploadFile(param1, url, file, param2, param3) {
|
|
318
|
+
let axios2;
|
|
319
|
+
if (typeof param1 === "function") {
|
|
320
|
+
const user = param1();
|
|
321
|
+
axios2 = this.createAxiosInstance({
|
|
322
|
+
key: user?.key,
|
|
323
|
+
token: user?.token
|
|
324
|
+
});
|
|
325
|
+
} else {
|
|
326
|
+
axios2 = this.createAxiosInstance({
|
|
327
|
+
key: param1?.key,
|
|
328
|
+
token: param1?.token
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
const formData = new FormData();
|
|
332
|
+
if (param2 instanceof Array) {
|
|
333
|
+
if (file instanceof Array) {
|
|
334
|
+
param2.forEach((k, i) => {
|
|
335
|
+
formData.append(k, file[i]);
|
|
336
|
+
});
|
|
337
|
+
} else {
|
|
338
|
+
formData.append("file", file);
|
|
339
|
+
}
|
|
340
|
+
} else {
|
|
341
|
+
if (param2) {
|
|
342
|
+
formData.append("param", JSON.stringify(param2));
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
if (param3) {
|
|
346
|
+
formData.append("param", JSON.stringify(param3));
|
|
347
|
+
}
|
|
348
|
+
const response = await axios2.post(url, formData);
|
|
349
|
+
return response;
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
// src/config/core.ts
|
|
354
|
+
var cfg = {
|
|
355
|
+
axios: {
|
|
356
|
+
baseUrl: "",
|
|
357
|
+
timeout: 5e3,
|
|
358
|
+
headers: {
|
|
359
|
+
accept: "*/*",
|
|
360
|
+
lang: "TH",
|
|
361
|
+
post: {
|
|
362
|
+
contentType: "application/x-www-form-urlencoded"
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
},
|
|
366
|
+
app: {
|
|
367
|
+
redirectUrl: "/login",
|
|
368
|
+
apiKey: "",
|
|
369
|
+
timezone: "Asia/Bangkok"
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
function getConfig() {
|
|
373
|
+
return cfg;
|
|
374
|
+
}
|
|
375
|
+
function create(config) {
|
|
376
|
+
cfg = { ...cfg, ...config };
|
|
377
|
+
const http = new CoreHttp(cfg);
|
|
378
|
+
return http;
|
|
379
|
+
}
|
|
380
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
381
|
+
0 && (module.exports = {
|
|
382
|
+
catchError,
|
|
383
|
+
create
|
|
384
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { AxiosResponse } from 'axios';
|
|
2
|
+
|
|
3
|
+
declare function catchError<T, E extends new (err?: any) => Error>(promise: Promise<T>, errorToCatch?: E[]): Promise<[undefined, T] | [InstanceType<E>]>;
|
|
4
|
+
|
|
5
|
+
interface credential {
|
|
6
|
+
key: string | undefined;
|
|
7
|
+
token: string | undefined;
|
|
8
|
+
}
|
|
9
|
+
declare class CoreHttp {
|
|
10
|
+
private config;
|
|
11
|
+
constructor(config: AbbotConfig);
|
|
12
|
+
private createAxiosInstance;
|
|
13
|
+
post<T, U extends credential = credential>(middleware: () => U | null, url: string, param?: Record<string, any> | null): Promise<AxiosResponse<T>>;
|
|
14
|
+
post<T, U extends credential = credential>(user: U | null, url: string, param?: Record<string, any> | null): Promise<AxiosResponse<T>>;
|
|
15
|
+
get<T, U extends credential = credential>(middleware: () => U | null, url: string): Promise<AxiosResponse<T>>;
|
|
16
|
+
get<T, U extends credential = credential>(user: U | null, url: string): Promise<AxiosResponse<T>>;
|
|
17
|
+
uploadFile<T, U extends credential = credential>(middleware: () => U | null, url: string, file: File, param?: Record<string, any> | null): Promise<AxiosResponse<T>>;
|
|
18
|
+
uploadFile<T, U extends credential = credential>(middleware: () => U | null, url: string, file: File[], fileKeys: string[], param?: Record<string, any> | null): Promise<AxiosResponse<T>>;
|
|
19
|
+
uploadFile<T, U extends credential = credential>(user: U | null, url: string, file: File, param?: Record<string, any> | null): Promise<AxiosResponse<T>>;
|
|
20
|
+
uploadFile<T, U extends credential = credential>(user: U | null, url: string, file: File[], fileKeys: string[], param?: Record<string, any> | null): Promise<AxiosResponse<T>>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface AbbotConfig {
|
|
24
|
+
axios?: {
|
|
25
|
+
baseUrl?: string;
|
|
26
|
+
headers?: {
|
|
27
|
+
accept?: string;
|
|
28
|
+
lang?: string;
|
|
29
|
+
post?: {
|
|
30
|
+
contentType?: string;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
timeout?: number;
|
|
34
|
+
};
|
|
35
|
+
app?: {
|
|
36
|
+
redirectUrl?: string;
|
|
37
|
+
apiKey?: string;
|
|
38
|
+
timezone?: string;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
declare function create(config: AbbotConfig): CoreHttp;
|
|
42
|
+
|
|
43
|
+
export { type AbbotConfig, catchError, create };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { AxiosResponse } from 'axios';
|
|
2
|
+
|
|
3
|
+
declare function catchError<T, E extends new (err?: any) => Error>(promise: Promise<T>, errorToCatch?: E[]): Promise<[undefined, T] | [InstanceType<E>]>;
|
|
4
|
+
|
|
5
|
+
interface credential {
|
|
6
|
+
key: string | undefined;
|
|
7
|
+
token: string | undefined;
|
|
8
|
+
}
|
|
9
|
+
declare class CoreHttp {
|
|
10
|
+
private config;
|
|
11
|
+
constructor(config: AbbotConfig);
|
|
12
|
+
private createAxiosInstance;
|
|
13
|
+
post<T, U extends credential = credential>(middleware: () => U | null, url: string, param?: Record<string, any> | null): Promise<AxiosResponse<T>>;
|
|
14
|
+
post<T, U extends credential = credential>(user: U | null, url: string, param?: Record<string, any> | null): Promise<AxiosResponse<T>>;
|
|
15
|
+
get<T, U extends credential = credential>(middleware: () => U | null, url: string): Promise<AxiosResponse<T>>;
|
|
16
|
+
get<T, U extends credential = credential>(user: U | null, url: string): Promise<AxiosResponse<T>>;
|
|
17
|
+
uploadFile<T, U extends credential = credential>(middleware: () => U | null, url: string, file: File, param?: Record<string, any> | null): Promise<AxiosResponse<T>>;
|
|
18
|
+
uploadFile<T, U extends credential = credential>(middleware: () => U | null, url: string, file: File[], fileKeys: string[], param?: Record<string, any> | null): Promise<AxiosResponse<T>>;
|
|
19
|
+
uploadFile<T, U extends credential = credential>(user: U | null, url: string, file: File, param?: Record<string, any> | null): Promise<AxiosResponse<T>>;
|
|
20
|
+
uploadFile<T, U extends credential = credential>(user: U | null, url: string, file: File[], fileKeys: string[], param?: Record<string, any> | null): Promise<AxiosResponse<T>>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface AbbotConfig {
|
|
24
|
+
axios?: {
|
|
25
|
+
baseUrl?: string;
|
|
26
|
+
headers?: {
|
|
27
|
+
accept?: string;
|
|
28
|
+
lang?: string;
|
|
29
|
+
post?: {
|
|
30
|
+
contentType?: string;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
timeout?: number;
|
|
34
|
+
};
|
|
35
|
+
app?: {
|
|
36
|
+
redirectUrl?: string;
|
|
37
|
+
apiKey?: string;
|
|
38
|
+
timezone?: string;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
declare function create(config: AbbotConfig): CoreHttp;
|
|
42
|
+
|
|
43
|
+
export { type AbbotConfig, catchError, create };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
// src/catchError.ts
|
|
2
|
+
async function catchError(promise, errorToCatch) {
|
|
3
|
+
return promise.then((data) => [void 0, data]).catch((error) => {
|
|
4
|
+
if (errorToCatch === void 0) return [error];
|
|
5
|
+
if (errorToCatch.some((e) => error instanceof e)) return [error];
|
|
6
|
+
throw error;
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// src/http.ts
|
|
11
|
+
import { AxiosError } from "axios";
|
|
12
|
+
|
|
13
|
+
// src/encryption/secure.ts
|
|
14
|
+
var Secure = class {
|
|
15
|
+
static keySize = 16;
|
|
16
|
+
static a = 5;
|
|
17
|
+
static b = 9;
|
|
18
|
+
static char = "0123456789";
|
|
19
|
+
static createId = () => {
|
|
20
|
+
const keyId = Array(this.keySize).fill("").map(() => {
|
|
21
|
+
const value = Math.floor(Math.random() * 10);
|
|
22
|
+
return this.char[value];
|
|
23
|
+
});
|
|
24
|
+
return keyId.join("");
|
|
25
|
+
};
|
|
26
|
+
static createKey = (keyId) => {
|
|
27
|
+
const crKey = Array(this.keySize).fill("").map((_, i) => Number(this.a ** Number(keyId[i]) % this.b));
|
|
28
|
+
return crKey.join("");
|
|
29
|
+
};
|
|
30
|
+
static toBase64Length16 = (text) => {
|
|
31
|
+
if (text && text.length) {
|
|
32
|
+
const b64 = Buffer.from(encodeURI(text)).toString("base64");
|
|
33
|
+
return b64.substring(0, 16);
|
|
34
|
+
}
|
|
35
|
+
return "";
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// src/encryption/cryp.ts
|
|
40
|
+
import { AES, enc, mode, pad } from "crypto-ts";
|
|
41
|
+
|
|
42
|
+
// src/encryption/es.ts
|
|
43
|
+
var ES = class {
|
|
44
|
+
static e(value) {
|
|
45
|
+
return Array.from(value).map((c) => c.charCodeAt(0)).reverse().map((e, i) => i % 2 === 0 ? e + 1 : e - 1).map((e, i) => i % 3 === 0 ? e * 2 : e);
|
|
46
|
+
}
|
|
47
|
+
static d(value) {
|
|
48
|
+
const result = value.map((e, i) => i % 3 === 0 ? Math.round(e / 2) : e).map((e, i) => i % 2 === 0 ? e - 1 : e + 1);
|
|
49
|
+
return String.fromCharCode.apply(null, result.reverse());
|
|
50
|
+
}
|
|
51
|
+
static a2b(value) {
|
|
52
|
+
const charactors = "abcdefghijklmnopqrstuvwxyz";
|
|
53
|
+
const randomChar = (max) => Math.floor(Math.random() * max);
|
|
54
|
+
const result = value.map(
|
|
55
|
+
(e, i) => `${String(e)}${i === value.length - 1 ? "" : charactors[randomChar(26)]}`
|
|
56
|
+
).join("");
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
static b2a(value) {
|
|
60
|
+
if (!value) return [];
|
|
61
|
+
const result = value.split(/[a-z]/);
|
|
62
|
+
return result.map((e) => Number(e));
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// src/encryption/cryp.ts
|
|
67
|
+
var Cryp = class {
|
|
68
|
+
ivText;
|
|
69
|
+
key;
|
|
70
|
+
keyBuffer;
|
|
71
|
+
iv;
|
|
72
|
+
algConfig;
|
|
73
|
+
constructor(cryptProps) {
|
|
74
|
+
this.ivText = cryptProps.iv;
|
|
75
|
+
this.key = cryptProps.keyValue ? cryptProps.keyValue : ES.d(ES.b2a(getConfig().app?.apiKey));
|
|
76
|
+
this.keyBuffer = enc.Utf8.parse(this.key);
|
|
77
|
+
this.iv = enc.Utf8.parse(this.ivText);
|
|
78
|
+
this.algConfig = { mode: mode.CBC, padding: pad.PKCS7, iv: this.iv };
|
|
79
|
+
}
|
|
80
|
+
encrypt(textValue) {
|
|
81
|
+
if (!textValue) return "";
|
|
82
|
+
if (!textValue.length) return textValue;
|
|
83
|
+
const cipher = AES.encrypt(textValue, this.keyBuffer, this.algConfig);
|
|
84
|
+
return cipher.toString();
|
|
85
|
+
}
|
|
86
|
+
decrypt(encryptedValue) {
|
|
87
|
+
try {
|
|
88
|
+
if (!encryptedValue || !encryptedValue.length) return null;
|
|
89
|
+
const decryptValue = AES.decrypt(
|
|
90
|
+
encryptedValue,
|
|
91
|
+
this.keyBuffer,
|
|
92
|
+
this.algConfig
|
|
93
|
+
);
|
|
94
|
+
const decryptData = decryptValue.toString(enc.Utf8);
|
|
95
|
+
const jsonData = JSON.parse(decryptData);
|
|
96
|
+
return jsonData;
|
|
97
|
+
} catch (err) {
|
|
98
|
+
console.error(err);
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
// src/config/axiosFn.ts
|
|
105
|
+
import axios from "axios";
|
|
106
|
+
function axiosConf(cfg2) {
|
|
107
|
+
const axiosObj = axios.create({
|
|
108
|
+
baseURL: cfg2.axios?.baseUrl,
|
|
109
|
+
headers: {
|
|
110
|
+
common: {
|
|
111
|
+
Accept: cfg2.axios?.headers?.accept,
|
|
112
|
+
"Accept-Language": cfg2.axios?.headers?.lang
|
|
113
|
+
},
|
|
114
|
+
post: {
|
|
115
|
+
"Content-Type": cfg2.axios?.headers?.post?.contentType
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
timeout: cfg2.axios?.timeout,
|
|
119
|
+
withCredentials: true
|
|
120
|
+
});
|
|
121
|
+
return axiosObj;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// src/http.ts
|
|
125
|
+
var CoreHttp = class {
|
|
126
|
+
config;
|
|
127
|
+
constructor(config) {
|
|
128
|
+
this.config = config;
|
|
129
|
+
}
|
|
130
|
+
createAxiosInstance(user) {
|
|
131
|
+
const axios2 = axiosConf(this.config);
|
|
132
|
+
const iv = Secure.createId();
|
|
133
|
+
const cryp = new Cryp({
|
|
134
|
+
iv,
|
|
135
|
+
keyValue: user.key
|
|
136
|
+
});
|
|
137
|
+
axios2.interceptors.request.use(
|
|
138
|
+
(config) => {
|
|
139
|
+
const req = { ...config };
|
|
140
|
+
if (config.method && config.method.toLowerCase() === "post") {
|
|
141
|
+
if (config.data) {
|
|
142
|
+
if (config.data instanceof FormData) {
|
|
143
|
+
if (config.data.get("param")) {
|
|
144
|
+
config.data.set(
|
|
145
|
+
"param",
|
|
146
|
+
cryp.encrypt(config.data.get("param")?.toString())
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
} else {
|
|
150
|
+
const payload = {};
|
|
151
|
+
payload.param = cryp.encrypt(JSON.stringify(config.data));
|
|
152
|
+
const body = payload ? new URLSearchParams(payload).toString() : "";
|
|
153
|
+
req.data = body;
|
|
154
|
+
req.headers.setContentType("application/x-www-form-urlencoded");
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
req.headers.set("data-code", iv);
|
|
159
|
+
if (user.token) {
|
|
160
|
+
req.headers.setAuthorization(`Bearer ${user.token}`);
|
|
161
|
+
}
|
|
162
|
+
return req;
|
|
163
|
+
},
|
|
164
|
+
(error) => Promise.reject(error)
|
|
165
|
+
);
|
|
166
|
+
axios2.interceptors.response.use(
|
|
167
|
+
(response) => {
|
|
168
|
+
const res = { ...response };
|
|
169
|
+
res.data = cryp.decrypt(response.data);
|
|
170
|
+
return res.data;
|
|
171
|
+
},
|
|
172
|
+
(error) => {
|
|
173
|
+
const err = {
|
|
174
|
+
message: error.message,
|
|
175
|
+
code: error.code,
|
|
176
|
+
config: error.config,
|
|
177
|
+
request: error.request
|
|
178
|
+
};
|
|
179
|
+
if (error.response) {
|
|
180
|
+
if (error.response.data) {
|
|
181
|
+
const response = cryp.decrypt(error.response.data);
|
|
182
|
+
err.response = response;
|
|
183
|
+
return Promise.reject(
|
|
184
|
+
new AxiosError(
|
|
185
|
+
err.message,
|
|
186
|
+
err.code,
|
|
187
|
+
err.config,
|
|
188
|
+
err.request,
|
|
189
|
+
err.response
|
|
190
|
+
)
|
|
191
|
+
);
|
|
192
|
+
} else {
|
|
193
|
+
err.response = {
|
|
194
|
+
status: "error",
|
|
195
|
+
code: error.response.status,
|
|
196
|
+
message: error.message,
|
|
197
|
+
data: null
|
|
198
|
+
};
|
|
199
|
+
return Promise.reject(
|
|
200
|
+
new AxiosError(
|
|
201
|
+
err.message,
|
|
202
|
+
err.code,
|
|
203
|
+
err.config,
|
|
204
|
+
err.request,
|
|
205
|
+
err.response
|
|
206
|
+
)
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
} else if (error.request) {
|
|
210
|
+
err.response = {
|
|
211
|
+
status: "error",
|
|
212
|
+
code: 0,
|
|
213
|
+
message: "No response received",
|
|
214
|
+
data: null
|
|
215
|
+
};
|
|
216
|
+
return Promise.reject(
|
|
217
|
+
new AxiosError(
|
|
218
|
+
err.message,
|
|
219
|
+
err.code,
|
|
220
|
+
err.config,
|
|
221
|
+
err.request,
|
|
222
|
+
err.response
|
|
223
|
+
)
|
|
224
|
+
);
|
|
225
|
+
} else {
|
|
226
|
+
err.response = {
|
|
227
|
+
status: "error",
|
|
228
|
+
code: 0,
|
|
229
|
+
message: error.message,
|
|
230
|
+
data: null
|
|
231
|
+
};
|
|
232
|
+
return Promise.reject(
|
|
233
|
+
new AxiosError(
|
|
234
|
+
err.message,
|
|
235
|
+
err.code,
|
|
236
|
+
err.config,
|
|
237
|
+
err.request,
|
|
238
|
+
err.response
|
|
239
|
+
)
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
);
|
|
244
|
+
return axios2;
|
|
245
|
+
}
|
|
246
|
+
async post(param1, url, param) {
|
|
247
|
+
let axios2;
|
|
248
|
+
if (typeof param1 === "function") {
|
|
249
|
+
const user = param1();
|
|
250
|
+
axios2 = this.createAxiosInstance({
|
|
251
|
+
key: user?.key,
|
|
252
|
+
token: user?.token
|
|
253
|
+
});
|
|
254
|
+
} else {
|
|
255
|
+
axios2 = this.createAxiosInstance({
|
|
256
|
+
key: param1?.key,
|
|
257
|
+
token: param1?.token
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
const response = await axios2.post(url, param);
|
|
261
|
+
return response;
|
|
262
|
+
}
|
|
263
|
+
async get(param1, url) {
|
|
264
|
+
let axios2;
|
|
265
|
+
if (typeof param1 === "function") {
|
|
266
|
+
const user = param1();
|
|
267
|
+
axios2 = this.createAxiosInstance({
|
|
268
|
+
key: user?.key,
|
|
269
|
+
token: user?.token
|
|
270
|
+
});
|
|
271
|
+
} else {
|
|
272
|
+
axios2 = this.createAxiosInstance({
|
|
273
|
+
key: param1?.key,
|
|
274
|
+
token: param1?.token
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
const response = await axios2.get(url);
|
|
278
|
+
return response;
|
|
279
|
+
}
|
|
280
|
+
async uploadFile(param1, url, file, param2, param3) {
|
|
281
|
+
let axios2;
|
|
282
|
+
if (typeof param1 === "function") {
|
|
283
|
+
const user = param1();
|
|
284
|
+
axios2 = this.createAxiosInstance({
|
|
285
|
+
key: user?.key,
|
|
286
|
+
token: user?.token
|
|
287
|
+
});
|
|
288
|
+
} else {
|
|
289
|
+
axios2 = this.createAxiosInstance({
|
|
290
|
+
key: param1?.key,
|
|
291
|
+
token: param1?.token
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
const formData = new FormData();
|
|
295
|
+
if (param2 instanceof Array) {
|
|
296
|
+
if (file instanceof Array) {
|
|
297
|
+
param2.forEach((k, i) => {
|
|
298
|
+
formData.append(k, file[i]);
|
|
299
|
+
});
|
|
300
|
+
} else {
|
|
301
|
+
formData.append("file", file);
|
|
302
|
+
}
|
|
303
|
+
} else {
|
|
304
|
+
if (param2) {
|
|
305
|
+
formData.append("param", JSON.stringify(param2));
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
if (param3) {
|
|
309
|
+
formData.append("param", JSON.stringify(param3));
|
|
310
|
+
}
|
|
311
|
+
const response = await axios2.post(url, formData);
|
|
312
|
+
return response;
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
// src/config/core.ts
|
|
317
|
+
var cfg = {
|
|
318
|
+
axios: {
|
|
319
|
+
baseUrl: "",
|
|
320
|
+
timeout: 5e3,
|
|
321
|
+
headers: {
|
|
322
|
+
accept: "*/*",
|
|
323
|
+
lang: "TH",
|
|
324
|
+
post: {
|
|
325
|
+
contentType: "application/x-www-form-urlencoded"
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
},
|
|
329
|
+
app: {
|
|
330
|
+
redirectUrl: "/login",
|
|
331
|
+
apiKey: "",
|
|
332
|
+
timezone: "Asia/Bangkok"
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
function getConfig() {
|
|
336
|
+
return cfg;
|
|
337
|
+
}
|
|
338
|
+
function create(config) {
|
|
339
|
+
cfg = { ...cfg, ...config };
|
|
340
|
+
const http = new CoreHttp(cfg);
|
|
341
|
+
return http;
|
|
342
|
+
}
|
|
343
|
+
export {
|
|
344
|
+
catchError,
|
|
345
|
+
create
|
|
346
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import js from "@eslint/js";
|
|
2
|
+
import globals from "globals";
|
|
3
|
+
import tseslint from "typescript-eslint";
|
|
4
|
+
import json from "@eslint/json";
|
|
5
|
+
import { defineConfig } from "eslint/config";
|
|
6
|
+
|
|
7
|
+
export default defineConfig([
|
|
8
|
+
{
|
|
9
|
+
files: ["**/*.{js,mjs,cjs,ts,mts,cts}"],
|
|
10
|
+
plugins: { js },
|
|
11
|
+
extends: ["js/recommended"],
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
files: ["**/*.{js,mjs,cjs,ts,mts,cts}"],
|
|
15
|
+
languageOptions: { globals: globals.browser },
|
|
16
|
+
},
|
|
17
|
+
tseslint.configs.recommended,
|
|
18
|
+
{
|
|
19
|
+
files: ["**/*.json"],
|
|
20
|
+
plugins: { json },
|
|
21
|
+
language: "json/json",
|
|
22
|
+
extends: ["json/recommended"],
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
files: ["**/*.jsonc"],
|
|
26
|
+
plugins: { json },
|
|
27
|
+
language: "json/jsonc",
|
|
28
|
+
extends: ["json/recommended"],
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
rules: {
|
|
32
|
+
"@typescript-eslint/no-explicit-any": "off",
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
]);
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "abbot-http-client",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "This package helps Abbot team to handle all the axios requests.",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": "./dist/index.js",
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsup"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"HTTP requests",
|
|
15
|
+
"ABBOT"
|
|
16
|
+
],
|
|
17
|
+
"author": "Sahasawat",
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@types/node": "^24.0.1",
|
|
21
|
+
"axios": "^1.10.0",
|
|
22
|
+
"crypto-ts": "^1.0.2",
|
|
23
|
+
"ts-node": "^10.9.2",
|
|
24
|
+
"typescript": "^5.8.3"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@eslint/js": "^9.28.0",
|
|
28
|
+
"@eslint/json": "^0.12.0",
|
|
29
|
+
"eslint": "^9.28.0",
|
|
30
|
+
"globals": "^16.2.0",
|
|
31
|
+
"tsup": "^8.5.0",
|
|
32
|
+
"typescript-eslint": "^8.34.0"
|
|
33
|
+
}
|
|
34
|
+
}
|