@amaster.ai/http-client 1.0.0-beta.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/LICENSE +21 -0
- package/README.md +170 -0
- package/dist/index.cjs +103 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +42 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.js +101 -0
- package/dist/index.js.map +1 -0
- package/package.json +47 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Amaster Team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# @amaster.ai/http-client
|
|
2
|
+
|
|
3
|
+
Base HTTP client with error handling and response unwrapping for backend API communication.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🔄 Automatic backend response unwrapping (`{ status: 0, data: {...} }` → `{...}`)
|
|
8
|
+
- 📅 Backend datetime format conversion (`"2026-01-05 10:30:45"` → `"2026-01-05T10:30:45.000Z"`)
|
|
9
|
+
- ⚠️ Consistent error handling with normalized error messages
|
|
10
|
+
- 🔌 Built on Axios with full TypeScript support
|
|
11
|
+
- 🌳 Tree-shakeable ESM/CJS builds
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pnpm add @amaster.ai/http-client axios
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
> **Note:** `axios` is a peer dependency and must be installed separately.
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
### Basic Usage
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
import { createHttpClient } from "@amaster.ai/http-client";
|
|
27
|
+
|
|
28
|
+
const client = createHttpClient();
|
|
29
|
+
|
|
30
|
+
const result = await client.request({
|
|
31
|
+
url: "/api/users",
|
|
32
|
+
method: "get",
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
if (result.data) {
|
|
36
|
+
console.log(result.data);
|
|
37
|
+
} else {
|
|
38
|
+
console.error(result.error.message);
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### With Custom Axios Instance
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
import axios from "axios";
|
|
46
|
+
import { createHttpClient } from "@amaster.ai/http-client";
|
|
47
|
+
|
|
48
|
+
const instance = axios.create({
|
|
49
|
+
baseURL: "https://api.example.com",
|
|
50
|
+
timeout: 5000,
|
|
51
|
+
headers: {
|
|
52
|
+
"Authorization": "Bearer token",
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const client = createHttpClient(instance);
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Response Format
|
|
60
|
+
|
|
61
|
+
All requests return a `ClientResult<T>`:
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
type ClientResult<T> = {
|
|
65
|
+
data: T | null; // Response data (null on error)
|
|
66
|
+
error: ClientError | null; // Error details (null on success)
|
|
67
|
+
status: number; // HTTP status code
|
|
68
|
+
};
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Error Handling
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
const result = await client.request({
|
|
75
|
+
url: "/api/users/123",
|
|
76
|
+
method: "get",
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
if (result.error) {
|
|
80
|
+
console.error("Error:", result.error.message);
|
|
81
|
+
console.error("Status:", result.error.status);
|
|
82
|
+
console.error("Details:", result.error.details);
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Features in Detail
|
|
87
|
+
|
|
88
|
+
### Backend Response Unwrapping
|
|
89
|
+
|
|
90
|
+
The client automatically unwraps backend standard response format:
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
// Backend returns:
|
|
94
|
+
{
|
|
95
|
+
"status": 0,
|
|
96
|
+
"data": { "id": 1, "name": "John" }
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Client returns:
|
|
100
|
+
{
|
|
101
|
+
data: { "id": 1, "name": "John" },
|
|
102
|
+
error: null,
|
|
103
|
+
status: 200
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Datetime Conversion
|
|
108
|
+
|
|
109
|
+
Backend datetime strings are automatically converted to ISO 8601 format:
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
// Backend returns:
|
|
113
|
+
{
|
|
114
|
+
"createdAt": "2026-01-05 10:30:45"
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Client returns:
|
|
118
|
+
{
|
|
119
|
+
"createdAt": "2026-01-05T10:30:45.000Z"
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
This works recursively for nested objects and arrays.
|
|
124
|
+
|
|
125
|
+
### Error Normalization
|
|
126
|
+
|
|
127
|
+
The client normalizes various backend error formats:
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
// Backend may return any of:
|
|
131
|
+
{ "message": "Error" }
|
|
132
|
+
{ "error": "Error" }
|
|
133
|
+
{ "msg": "Error" }
|
|
134
|
+
{ "detail": "Error" }
|
|
135
|
+
|
|
136
|
+
// Client always returns:
|
|
137
|
+
{
|
|
138
|
+
error: {
|
|
139
|
+
message: "Error",
|
|
140
|
+
status: 400,
|
|
141
|
+
details: { /* original response */ }
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## TypeScript Support
|
|
147
|
+
|
|
148
|
+
Full TypeScript support with generic types:
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
interface User {
|
|
152
|
+
id: number;
|
|
153
|
+
name: string;
|
|
154
|
+
email: string;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const result = await client.request<User>({
|
|
158
|
+
url: "/api/users/1",
|
|
159
|
+
method: "get",
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
if (result.data) {
|
|
163
|
+
// result.data is typed as User
|
|
164
|
+
console.log(result.data.name);
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## License
|
|
169
|
+
|
|
170
|
+
MIT
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/http.ts
|
|
4
|
+
function normalizeErrorMessage(payload) {
|
|
5
|
+
if (!payload) {
|
|
6
|
+
return "Request failed";
|
|
7
|
+
}
|
|
8
|
+
if (typeof payload === "string") {
|
|
9
|
+
return payload;
|
|
10
|
+
}
|
|
11
|
+
if (typeof payload === "object") {
|
|
12
|
+
const errorPayload = payload;
|
|
13
|
+
return errorPayload.message || errorPayload.error || errorPayload.msg || errorPayload.detail || "Request failed";
|
|
14
|
+
}
|
|
15
|
+
return "Request failed";
|
|
16
|
+
}
|
|
17
|
+
function isBackendStandardFormat(data) {
|
|
18
|
+
if (!data || typeof data !== "object" || !("data" in data)) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
if ("status" in data) {
|
|
22
|
+
const status = data.status;
|
|
23
|
+
return status === 0 || status === 1 || status === "0" || status === "1";
|
|
24
|
+
}
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
function unwrapBackendResponse(responseData) {
|
|
28
|
+
if (isBackendStandardFormat(responseData)) {
|
|
29
|
+
return responseData.data;
|
|
30
|
+
}
|
|
31
|
+
return responseData;
|
|
32
|
+
}
|
|
33
|
+
var BACKEND_DATETIME_REGEX = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/;
|
|
34
|
+
function isBackendDatetime(value) {
|
|
35
|
+
return BACKEND_DATETIME_REGEX.test(value);
|
|
36
|
+
}
|
|
37
|
+
function parseBackendDatetime(value) {
|
|
38
|
+
return `${value.replace(" ", "T")}.000Z`;
|
|
39
|
+
}
|
|
40
|
+
function processResponseDates(data) {
|
|
41
|
+
if (data === null || data === void 0) {
|
|
42
|
+
return data;
|
|
43
|
+
}
|
|
44
|
+
if (Array.isArray(data)) {
|
|
45
|
+
return data.map((item) => processResponseDates(item));
|
|
46
|
+
}
|
|
47
|
+
if (typeof data === "object") {
|
|
48
|
+
const processed = {};
|
|
49
|
+
for (const [key, value] of Object.entries(data)) {
|
|
50
|
+
processed[key] = processResponseDates(value);
|
|
51
|
+
}
|
|
52
|
+
return processed;
|
|
53
|
+
}
|
|
54
|
+
if (typeof data === "string" && isBackendDatetime(data)) {
|
|
55
|
+
return parseBackendDatetime(data);
|
|
56
|
+
}
|
|
57
|
+
return data;
|
|
58
|
+
}
|
|
59
|
+
function createHttpClient(axiosInstance) {
|
|
60
|
+
let instance = axiosInstance;
|
|
61
|
+
return {
|
|
62
|
+
async request(config) {
|
|
63
|
+
if (!instance) {
|
|
64
|
+
const axios = await import('axios');
|
|
65
|
+
instance = axios.default.create();
|
|
66
|
+
}
|
|
67
|
+
try {
|
|
68
|
+
const resp = await instance(config);
|
|
69
|
+
const status = resp?.status ?? 0;
|
|
70
|
+
if (status >= 200 && status < 300) {
|
|
71
|
+
const unwrappedData = unwrapBackendResponse(resp?.data);
|
|
72
|
+
const processedData = processResponseDates(unwrappedData);
|
|
73
|
+
return { data: processedData ?? null, error: null, status };
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
data: null,
|
|
77
|
+
error: {
|
|
78
|
+
status,
|
|
79
|
+
message: normalizeErrorMessage(resp?.data) || `HTTP ${status}`,
|
|
80
|
+
details: resp?.data
|
|
81
|
+
},
|
|
82
|
+
status
|
|
83
|
+
};
|
|
84
|
+
} catch (error_) {
|
|
85
|
+
const error = error_;
|
|
86
|
+
const status = error.response?.status || 0;
|
|
87
|
+
return {
|
|
88
|
+
data: null,
|
|
89
|
+
error: {
|
|
90
|
+
status,
|
|
91
|
+
message: normalizeErrorMessage(error.response?.data) || error.message || "Network error",
|
|
92
|
+
details: error.response?.data
|
|
93
|
+
},
|
|
94
|
+
status
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
exports.createHttpClient = createHttpClient;
|
|
102
|
+
//# sourceMappingURL=index.cjs.map
|
|
103
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/http.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["import type { AxiosInstance, AxiosRequestConfig } from \"axios\";\n\nexport type ClientError = {\n message: string;\n status?: number;\n code?: string;\n details?: unknown;\n};\n\nexport type ClientResult<T> = {\n data: T | null;\n error: ClientError | null;\n status: number;\n};\n\nexport type HttpClient = {\n request<T>(\n config: AxiosRequestConfig & {\n url: string;\n method: NonNullable<AxiosRequestConfig[\"method\"]>;\n }\n ): Promise<ClientResult<T>>;\n};\n\ninterface ErrorPayload {\n message?: string;\n error?: string;\n msg?: string;\n detail?: string;\n}\n\nfunction normalizeErrorMessage(payload: unknown): string {\n if (!payload) {\n return \"Request failed\";\n }\n if (typeof payload === \"string\") {\n return payload;\n }\n if (typeof payload === \"object\") {\n const errorPayload = payload as ErrorPayload;\n return (\n errorPayload.message ||\n errorPayload.error ||\n errorPayload.msg ||\n errorPayload.detail ||\n \"Request failed\"\n );\n }\n return \"Request failed\";\n}\n\ninterface BackendStandardResponse {\n status: number | string;\n data: unknown;\n}\n\n/**\n * Check if response data matches backend standard format: { status: 0/1, data: {...} }\n * Handles both number and string status values\n */\nfunction isBackendStandardFormat(data: unknown): data is BackendStandardResponse {\n if (!data || typeof data !== \"object\" || !(\"data\" in data)) {\n return false;\n }\n\n // Check status field - handle both number and string values\n if (\"status\" in data) {\n const status = (data as BackendStandardResponse).status;\n // Accept 0, 1, \"0\", \"1\" as valid status values\n return status === 0 || status === 1 || status === \"0\" || status === \"1\";\n }\n\n return false;\n}\n\n/**\n * Unwrap backend standard format response\n * Backend returns: { status: 0, data: {...} }\n * We extract the inner 'data' field for cleaner client usage\n */\nfunction unwrapBackendResponse<T>(responseData: unknown): T {\n if (isBackendStandardFormat(responseData)) {\n // Extract inner data field\n return responseData.data as T;\n }\n // Return as-is if not standard format (e.g., BPM/Workflow APIs)\n return responseData as T;\n}\n\n/**\n * Backend datetime format regex: \"YYYY-MM-DD HH:MM:SS\"\n */\nconst BACKEND_DATETIME_REGEX = /^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$/;\n\n/**\n * Check if a string matches backend datetime format\n */\nfunction isBackendDatetime(value: string): boolean {\n return BACKEND_DATETIME_REGEX.test(value);\n}\n\n/**\n * Convert backend datetime string to ISO 8601 format\n * \"2026-01-05 10:30:45\" → \"2026-01-05T10:30:45.000Z\"\n */\nfunction parseBackendDatetime(value: string): string {\n // Replace space with T and append Z for UTC\n return `${value.replace(\" \", \"T\")}.000Z`;\n}\n\n/**\n * Recursively process response data to convert backend datetime strings to ISO format\n * Handles nested objects and arrays\n */\nfunction processResponseDates(data: unknown): unknown {\n if (data === null || data === undefined) {\n return data;\n }\n\n // Handle arrays\n if (Array.isArray(data)) {\n return data.map((item) => processResponseDates(item));\n }\n\n // Handle objects\n if (typeof data === \"object\") {\n const processed: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n processed[key] = processResponseDates(value);\n }\n return processed;\n }\n\n // Handle backend datetime strings\n if (typeof data === \"string\" && isBackendDatetime(data)) {\n return parseBackendDatetime(data);\n }\n\n return data;\n}\n\n/**\n * Create an HTTP client instance\n * \n * @param axiosInstance - Optional axios instance to use (defaults to a basic axios instance)\n * @returns HttpClient with request method\n * \n * @example\n * ```typescript\n * import axios from \"axios\";\n * import { createHttpClient } from \"@amaster.ai/http-client\";\n * \n * const instance = axios.create({ baseURL: \"https://api.example.com\" });\n * const client = createHttpClient(instance);\n * \n * const result = await client.request({\n * url: \"/users\",\n * method: \"get\",\n * });\n * ```\n */\nexport function createHttpClient(axiosInstance?: AxiosInstance): HttpClient {\n // Import axios dynamically to avoid bundling it\n let instance = axiosInstance;\n \n return {\n async request<T>(\n config: AxiosRequestConfig & {\n url: string;\n method: NonNullable<AxiosRequestConfig[\"method\"]>;\n }\n ) {\n // Lazy load axios if not provided\n if (!instance) {\n const axios = await import(\"axios\");\n instance = axios.default.create();\n }\n\n try {\n const resp = await instance(config);\n const status = resp?.status ?? 0;\n\n if (status >= 200 && status < 300) {\n // Unwrap backend standard format: { status: 0, data: {...} } -> {...}\n const unwrappedData = unwrapBackendResponse<T>(resp?.data);\n // Convert backend datetime strings to ISO format\n const processedData = processResponseDates(unwrappedData);\n return { data: (processedData ?? null) as T | null, error: null, status };\n }\n\n return {\n data: null,\n error: {\n status,\n message: normalizeErrorMessage(resp?.data) || `HTTP ${status}`,\n details: resp?.data,\n },\n status,\n };\n } catch (error_: unknown) {\n // Catch network errors, timeouts, and other axios exceptions\n const error = error_ as {\n response?: { status?: number; data?: unknown };\n message?: string;\n };\n const status = error.response?.status || 0;\n return {\n data: null,\n error: {\n status,\n message:\n normalizeErrorMessage(error.response?.data) || error.message || \"Network error\",\n details: error.response?.data,\n },\n status,\n };\n }\n },\n };\n}\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { AxiosRequestConfig, AxiosInstance } from 'axios';
|
|
2
|
+
|
|
3
|
+
type ClientError = {
|
|
4
|
+
message: string;
|
|
5
|
+
status?: number;
|
|
6
|
+
code?: string;
|
|
7
|
+
details?: unknown;
|
|
8
|
+
};
|
|
9
|
+
type ClientResult<T> = {
|
|
10
|
+
data: T | null;
|
|
11
|
+
error: ClientError | null;
|
|
12
|
+
status: number;
|
|
13
|
+
};
|
|
14
|
+
type HttpClient = {
|
|
15
|
+
request<T>(config: AxiosRequestConfig & {
|
|
16
|
+
url: string;
|
|
17
|
+
method: NonNullable<AxiosRequestConfig["method"]>;
|
|
18
|
+
}): Promise<ClientResult<T>>;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Create an HTTP client instance
|
|
22
|
+
*
|
|
23
|
+
* @param axiosInstance - Optional axios instance to use (defaults to a basic axios instance)
|
|
24
|
+
* @returns HttpClient with request method
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* import axios from "axios";
|
|
29
|
+
* import { createHttpClient } from "@amaster.ai/http-client";
|
|
30
|
+
*
|
|
31
|
+
* const instance = axios.create({ baseURL: "https://api.example.com" });
|
|
32
|
+
* const client = createHttpClient(instance);
|
|
33
|
+
*
|
|
34
|
+
* const result = await client.request({
|
|
35
|
+
* url: "/users",
|
|
36
|
+
* method: "get",
|
|
37
|
+
* });
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
declare function createHttpClient(axiosInstance?: AxiosInstance): HttpClient;
|
|
41
|
+
|
|
42
|
+
export { type ClientError, type ClientResult, type HttpClient, createHttpClient };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { AxiosRequestConfig, AxiosInstance } from 'axios';
|
|
2
|
+
|
|
3
|
+
type ClientError = {
|
|
4
|
+
message: string;
|
|
5
|
+
status?: number;
|
|
6
|
+
code?: string;
|
|
7
|
+
details?: unknown;
|
|
8
|
+
};
|
|
9
|
+
type ClientResult<T> = {
|
|
10
|
+
data: T | null;
|
|
11
|
+
error: ClientError | null;
|
|
12
|
+
status: number;
|
|
13
|
+
};
|
|
14
|
+
type HttpClient = {
|
|
15
|
+
request<T>(config: AxiosRequestConfig & {
|
|
16
|
+
url: string;
|
|
17
|
+
method: NonNullable<AxiosRequestConfig["method"]>;
|
|
18
|
+
}): Promise<ClientResult<T>>;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Create an HTTP client instance
|
|
22
|
+
*
|
|
23
|
+
* @param axiosInstance - Optional axios instance to use (defaults to a basic axios instance)
|
|
24
|
+
* @returns HttpClient with request method
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* import axios from "axios";
|
|
29
|
+
* import { createHttpClient } from "@amaster.ai/http-client";
|
|
30
|
+
*
|
|
31
|
+
* const instance = axios.create({ baseURL: "https://api.example.com" });
|
|
32
|
+
* const client = createHttpClient(instance);
|
|
33
|
+
*
|
|
34
|
+
* const result = await client.request({
|
|
35
|
+
* url: "/users",
|
|
36
|
+
* method: "get",
|
|
37
|
+
* });
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
declare function createHttpClient(axiosInstance?: AxiosInstance): HttpClient;
|
|
41
|
+
|
|
42
|
+
export { type ClientError, type ClientResult, type HttpClient, createHttpClient };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
// src/http.ts
|
|
2
|
+
function normalizeErrorMessage(payload) {
|
|
3
|
+
if (!payload) {
|
|
4
|
+
return "Request failed";
|
|
5
|
+
}
|
|
6
|
+
if (typeof payload === "string") {
|
|
7
|
+
return payload;
|
|
8
|
+
}
|
|
9
|
+
if (typeof payload === "object") {
|
|
10
|
+
const errorPayload = payload;
|
|
11
|
+
return errorPayload.message || errorPayload.error || errorPayload.msg || errorPayload.detail || "Request failed";
|
|
12
|
+
}
|
|
13
|
+
return "Request failed";
|
|
14
|
+
}
|
|
15
|
+
function isBackendStandardFormat(data) {
|
|
16
|
+
if (!data || typeof data !== "object" || !("data" in data)) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
if ("status" in data) {
|
|
20
|
+
const status = data.status;
|
|
21
|
+
return status === 0 || status === 1 || status === "0" || status === "1";
|
|
22
|
+
}
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
function unwrapBackendResponse(responseData) {
|
|
26
|
+
if (isBackendStandardFormat(responseData)) {
|
|
27
|
+
return responseData.data;
|
|
28
|
+
}
|
|
29
|
+
return responseData;
|
|
30
|
+
}
|
|
31
|
+
var BACKEND_DATETIME_REGEX = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/;
|
|
32
|
+
function isBackendDatetime(value) {
|
|
33
|
+
return BACKEND_DATETIME_REGEX.test(value);
|
|
34
|
+
}
|
|
35
|
+
function parseBackendDatetime(value) {
|
|
36
|
+
return `${value.replace(" ", "T")}.000Z`;
|
|
37
|
+
}
|
|
38
|
+
function processResponseDates(data) {
|
|
39
|
+
if (data === null || data === void 0) {
|
|
40
|
+
return data;
|
|
41
|
+
}
|
|
42
|
+
if (Array.isArray(data)) {
|
|
43
|
+
return data.map((item) => processResponseDates(item));
|
|
44
|
+
}
|
|
45
|
+
if (typeof data === "object") {
|
|
46
|
+
const processed = {};
|
|
47
|
+
for (const [key, value] of Object.entries(data)) {
|
|
48
|
+
processed[key] = processResponseDates(value);
|
|
49
|
+
}
|
|
50
|
+
return processed;
|
|
51
|
+
}
|
|
52
|
+
if (typeof data === "string" && isBackendDatetime(data)) {
|
|
53
|
+
return parseBackendDatetime(data);
|
|
54
|
+
}
|
|
55
|
+
return data;
|
|
56
|
+
}
|
|
57
|
+
function createHttpClient(axiosInstance) {
|
|
58
|
+
let instance = axiosInstance;
|
|
59
|
+
return {
|
|
60
|
+
async request(config) {
|
|
61
|
+
if (!instance) {
|
|
62
|
+
const axios = await import('axios');
|
|
63
|
+
instance = axios.default.create();
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
const resp = await instance(config);
|
|
67
|
+
const status = resp?.status ?? 0;
|
|
68
|
+
if (status >= 200 && status < 300) {
|
|
69
|
+
const unwrappedData = unwrapBackendResponse(resp?.data);
|
|
70
|
+
const processedData = processResponseDates(unwrappedData);
|
|
71
|
+
return { data: processedData ?? null, error: null, status };
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
data: null,
|
|
75
|
+
error: {
|
|
76
|
+
status,
|
|
77
|
+
message: normalizeErrorMessage(resp?.data) || `HTTP ${status}`,
|
|
78
|
+
details: resp?.data
|
|
79
|
+
},
|
|
80
|
+
status
|
|
81
|
+
};
|
|
82
|
+
} catch (error_) {
|
|
83
|
+
const error = error_;
|
|
84
|
+
const status = error.response?.status || 0;
|
|
85
|
+
return {
|
|
86
|
+
data: null,
|
|
87
|
+
error: {
|
|
88
|
+
status,
|
|
89
|
+
message: normalizeErrorMessage(error.response?.data) || error.message || "Network error",
|
|
90
|
+
details: error.response?.data
|
|
91
|
+
},
|
|
92
|
+
status
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export { createHttpClient };
|
|
100
|
+
//# sourceMappingURL=index.js.map
|
|
101
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/http.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { AxiosInstance, AxiosRequestConfig } from \"axios\";\n\nexport type ClientError = {\n message: string;\n status?: number;\n code?: string;\n details?: unknown;\n};\n\nexport type ClientResult<T> = {\n data: T | null;\n error: ClientError | null;\n status: number;\n};\n\nexport type HttpClient = {\n request<T>(\n config: AxiosRequestConfig & {\n url: string;\n method: NonNullable<AxiosRequestConfig[\"method\"]>;\n }\n ): Promise<ClientResult<T>>;\n};\n\ninterface ErrorPayload {\n message?: string;\n error?: string;\n msg?: string;\n detail?: string;\n}\n\nfunction normalizeErrorMessage(payload: unknown): string {\n if (!payload) {\n return \"Request failed\";\n }\n if (typeof payload === \"string\") {\n return payload;\n }\n if (typeof payload === \"object\") {\n const errorPayload = payload as ErrorPayload;\n return (\n errorPayload.message ||\n errorPayload.error ||\n errorPayload.msg ||\n errorPayload.detail ||\n \"Request failed\"\n );\n }\n return \"Request failed\";\n}\n\ninterface BackendStandardResponse {\n status: number | string;\n data: unknown;\n}\n\n/**\n * Check if response data matches backend standard format: { status: 0/1, data: {...} }\n * Handles both number and string status values\n */\nfunction isBackendStandardFormat(data: unknown): data is BackendStandardResponse {\n if (!data || typeof data !== \"object\" || !(\"data\" in data)) {\n return false;\n }\n\n // Check status field - handle both number and string values\n if (\"status\" in data) {\n const status = (data as BackendStandardResponse).status;\n // Accept 0, 1, \"0\", \"1\" as valid status values\n return status === 0 || status === 1 || status === \"0\" || status === \"1\";\n }\n\n return false;\n}\n\n/**\n * Unwrap backend standard format response\n * Backend returns: { status: 0, data: {...} }\n * We extract the inner 'data' field for cleaner client usage\n */\nfunction unwrapBackendResponse<T>(responseData: unknown): T {\n if (isBackendStandardFormat(responseData)) {\n // Extract inner data field\n return responseData.data as T;\n }\n // Return as-is if not standard format (e.g., BPM/Workflow APIs)\n return responseData as T;\n}\n\n/**\n * Backend datetime format regex: \"YYYY-MM-DD HH:MM:SS\"\n */\nconst BACKEND_DATETIME_REGEX = /^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$/;\n\n/**\n * Check if a string matches backend datetime format\n */\nfunction isBackendDatetime(value: string): boolean {\n return BACKEND_DATETIME_REGEX.test(value);\n}\n\n/**\n * Convert backend datetime string to ISO 8601 format\n * \"2026-01-05 10:30:45\" → \"2026-01-05T10:30:45.000Z\"\n */\nfunction parseBackendDatetime(value: string): string {\n // Replace space with T and append Z for UTC\n return `${value.replace(\" \", \"T\")}.000Z`;\n}\n\n/**\n * Recursively process response data to convert backend datetime strings to ISO format\n * Handles nested objects and arrays\n */\nfunction processResponseDates(data: unknown): unknown {\n if (data === null || data === undefined) {\n return data;\n }\n\n // Handle arrays\n if (Array.isArray(data)) {\n return data.map((item) => processResponseDates(item));\n }\n\n // Handle objects\n if (typeof data === \"object\") {\n const processed: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n processed[key] = processResponseDates(value);\n }\n return processed;\n }\n\n // Handle backend datetime strings\n if (typeof data === \"string\" && isBackendDatetime(data)) {\n return parseBackendDatetime(data);\n }\n\n return data;\n}\n\n/**\n * Create an HTTP client instance\n * \n * @param axiosInstance - Optional axios instance to use (defaults to a basic axios instance)\n * @returns HttpClient with request method\n * \n * @example\n * ```typescript\n * import axios from \"axios\";\n * import { createHttpClient } from \"@amaster.ai/http-client\";\n * \n * const instance = axios.create({ baseURL: \"https://api.example.com\" });\n * const client = createHttpClient(instance);\n * \n * const result = await client.request({\n * url: \"/users\",\n * method: \"get\",\n * });\n * ```\n */\nexport function createHttpClient(axiosInstance?: AxiosInstance): HttpClient {\n // Import axios dynamically to avoid bundling it\n let instance = axiosInstance;\n \n return {\n async request<T>(\n config: AxiosRequestConfig & {\n url: string;\n method: NonNullable<AxiosRequestConfig[\"method\"]>;\n }\n ) {\n // Lazy load axios if not provided\n if (!instance) {\n const axios = await import(\"axios\");\n instance = axios.default.create();\n }\n\n try {\n const resp = await instance(config);\n const status = resp?.status ?? 0;\n\n if (status >= 200 && status < 300) {\n // Unwrap backend standard format: { status: 0, data: {...} } -> {...}\n const unwrappedData = unwrapBackendResponse<T>(resp?.data);\n // Convert backend datetime strings to ISO format\n const processedData = processResponseDates(unwrappedData);\n return { data: (processedData ?? null) as T | null, error: null, status };\n }\n\n return {\n data: null,\n error: {\n status,\n message: normalizeErrorMessage(resp?.data) || `HTTP ${status}`,\n details: resp?.data,\n },\n status,\n };\n } catch (error_: unknown) {\n // Catch network errors, timeouts, and other axios exceptions\n const error = error_ as {\n response?: { status?: number; data?: unknown };\n message?: string;\n };\n const status = error.response?.status || 0;\n return {\n data: null,\n error: {\n status,\n message:\n normalizeErrorMessage(error.response?.data) || error.message || \"Network error\",\n details: error.response?.data,\n },\n status,\n };\n }\n },\n };\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@amaster.ai/http-client",
|
|
3
|
+
"version": "1.0.0-beta.0",
|
|
4
|
+
"description": "Base HTTP client with error handling and response unwrapping",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"require": "./dist/index.cjs",
|
|
13
|
+
"types": "./dist/index.d.ts"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"README.md"
|
|
19
|
+
],
|
|
20
|
+
"keywords": [
|
|
21
|
+
"http",
|
|
22
|
+
"client",
|
|
23
|
+
"axios",
|
|
24
|
+
"api",
|
|
25
|
+
"typescript"
|
|
26
|
+
],
|
|
27
|
+
"author": "Amaster Team",
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"publishConfig": {
|
|
30
|
+
"access": "public",
|
|
31
|
+
"registry": "https://registry.npmjs.org/"
|
|
32
|
+
},
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"axios": "^1.11.0"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"axios": "^1.11.0",
|
|
38
|
+
"tsup": "^8.3.5",
|
|
39
|
+
"typescript": "~5.7.2"
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "tsup",
|
|
43
|
+
"dev": "tsup --watch",
|
|
44
|
+
"clean": "rm -rf dist *.tsbuildinfo",
|
|
45
|
+
"type-check": "tsc --noEmit"
|
|
46
|
+
}
|
|
47
|
+
}
|