@adatechnology/http-client 0.0.1 → 0.0.2
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/CHANGELOG.md +6 -0
- package/dist/{types/http.interface.d.ts → index.d.ts} +28 -18
- package/dist/index.js +787 -11
- package/package.json +7 -3
- package/src/errors/base-app-error.ts +25 -0
- package/src/errors/error-mapper.service.ts +60 -0
- package/src/errors/http-client-error.ts +7 -0
- package/src/implementations/axios/axios.http.provider.ts +19 -1
- package/tsconfig.json +4 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/tsconfig.tsup.json +6 -0
- package/tsup.config.ts +14 -0
- package/dist/http.interface.js +0 -27
- package/dist/http.module.js +0 -37
- package/dist/http.provider.js +0 -137
- package/dist/http.token.js +0 -6
- package/dist/implementations/axios/axios.http.module.js +0 -41
- package/dist/implementations/axios/axios.http.provider.js +0 -424
- package/dist/implementations/axios/axios.http.token.js +0 -4
- package/dist/implementations/http.implementation.module.js +0 -20
- package/dist/types/http.module.d.ts +0 -9
- package/dist/types/http.provider.d.ts +0 -43
- package/dist/types/http.token.d.ts +0 -3
- package/dist/types/implementations/axios/axios.http.module.d.ts +0 -5
- package/dist/types/implementations/axios/axios.http.provider.d.ts +0 -226
- package/dist/types/implementations/axios/axios.http.token.d.ts +0 -1
- package/dist/types/implementations/http.implementation.module.d.ts +0 -2
- package/dist/types/index.d.ts +0 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adatechnology/http-client",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -8,12 +8,16 @@
|
|
|
8
8
|
"main": "dist/index.js",
|
|
9
9
|
"types": "dist/index.d.ts",
|
|
10
10
|
"peerDependencies": {
|
|
11
|
-
"@nestjs/common": "^11",
|
|
11
|
+
"@nestjs/common": "^11.0.16",
|
|
12
12
|
"@nestjs/core": "^11"
|
|
13
13
|
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@esbuild-plugins/tsconfig-paths": "^0.1.2",
|
|
16
|
+
"tsup": "^8.5.1"
|
|
17
|
+
},
|
|
14
18
|
"scripts": {
|
|
15
19
|
"prebuild": "rm -rf dist",
|
|
16
|
-
"build": "
|
|
20
|
+
"build": "tsup",
|
|
17
21
|
"check": "tsc -p tsconfig.json --noEmit"
|
|
18
22
|
}
|
|
19
23
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface ErrorContext {
|
|
2
|
+
service?: string;
|
|
3
|
+
url?: string;
|
|
4
|
+
method?: string;
|
|
5
|
+
origin?: { file?: string; fn?: string; line?: number; column?: number };
|
|
6
|
+
stack?: Array<{ fn?: string; file?: string; line?: number; column?: number }>;
|
|
7
|
+
[key: string]: any;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export class BaseAppError extends Error {
|
|
11
|
+
public readonly code?: string;
|
|
12
|
+
public readonly status?: number;
|
|
13
|
+
public readonly context?: ErrorContext;
|
|
14
|
+
|
|
15
|
+
constructor(message: string, status?: number, code?: string, context?: ErrorContext) {
|
|
16
|
+
super(message);
|
|
17
|
+
this.name = new.target.name;
|
|
18
|
+
this.status = status;
|
|
19
|
+
this.code = code;
|
|
20
|
+
this.context = context;
|
|
21
|
+
if (typeof Error.captureStackTrace === 'function') {
|
|
22
|
+
Error.captureStackTrace(this, new.target);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export class ErrorMapperService {
|
|
2
|
+
mapUpstreamError(err: unknown) {
|
|
3
|
+
if (err && (err as any).status && (err as any).message) return err;
|
|
4
|
+
|
|
5
|
+
try {
|
|
6
|
+
const anyErr: any = err as any;
|
|
7
|
+
const context: any = {};
|
|
8
|
+
|
|
9
|
+
if (anyErr?.config) {
|
|
10
|
+
context.url = anyErr.config.url || anyErr.config.baseURL;
|
|
11
|
+
context.method = anyErr.config.method;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (anyErr?.stack) {
|
|
15
|
+
const frames = this.parseStack(anyErr.stack);
|
|
16
|
+
if (frames.length) {
|
|
17
|
+
context.stack = frames;
|
|
18
|
+
const origin = frames.find((f) => !this.isInternalFrame(f.file));
|
|
19
|
+
if (origin) context.origin = origin;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (anyErr?.response) {
|
|
24
|
+
const status = anyErr.response.status || 502;
|
|
25
|
+
const message = anyErr.response.data?.message || anyErr.message || 'Upstream error';
|
|
26
|
+
return { message, status, code: anyErr.code, context };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (anyErr?.request) {
|
|
30
|
+
return { message: 'No response from upstream service', status: 502, code: anyErr.code, context };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return { message: (anyErr && anyErr.message) || 'Unexpected error', status: 500, code: anyErr?.code, context };
|
|
34
|
+
} catch (e) {
|
|
35
|
+
return { message: 'Error mapping failure', status: 500, code: undefined, context: { original: String(err) } };
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private parseStack(stack: string) {
|
|
40
|
+
const lines = stack.split('\n').map((l) => l.trim()).filter(Boolean);
|
|
41
|
+
const frames: Array<any> = [];
|
|
42
|
+
const re = /^at\s+(?:(.*?)\s+\()?(.*?):(\d+):(\d+)\)?$/;
|
|
43
|
+
for (const line of lines) {
|
|
44
|
+
const m = re.exec(line);
|
|
45
|
+
if (m) {
|
|
46
|
+
const fn = m[1] || undefined;
|
|
47
|
+
const file = m[2];
|
|
48
|
+
const lineNum = parseInt(m[3], 10);
|
|
49
|
+
const colNum = parseInt(m[4], 10);
|
|
50
|
+
frames.push({ fn, file, line: lineNum, column: colNum });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return frames;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
private isInternalFrame(file?: string) {
|
|
57
|
+
if (!file) return false;
|
|
58
|
+
return /node_modules|internal|axios/.test(file);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { BaseAppError } from "./base-app-error";
|
|
2
|
+
|
|
3
|
+
export class HttpClientError extends BaseAppError {
|
|
4
|
+
constructor(message: string, status?: number, code?: string, context?: Record<string, any>) {
|
|
5
|
+
super(message, status ?? 502, code, { service: '@adatechnology/http-client', ...(context || {}) });
|
|
6
|
+
}
|
|
7
|
+
}
|
|
@@ -584,7 +584,25 @@ export class AxiosHttpProvider implements AxiosHttpProviderInterface {
|
|
|
584
584
|
return await method();
|
|
585
585
|
} catch (error) {
|
|
586
586
|
const processedError = await this.processErrorInterceptors(error);
|
|
587
|
-
|
|
587
|
+
// Map to a normalized application error with context
|
|
588
|
+
try {
|
|
589
|
+
// lazy import to avoid circular deps at runtime - use local mapper
|
|
590
|
+
const { ErrorMapperService } = require("../../errors/error-mapper.service");
|
|
591
|
+
const { HttpClientError } = require("../../errors/http-client-error");
|
|
592
|
+
const mapper = new ErrorMapperService();
|
|
593
|
+
const mapped = mapper.mapUpstreamError(processedError);
|
|
594
|
+
throw new HttpClientError(mapped.message, mapped.status, mapped.code, mapped.context);
|
|
595
|
+
} catch (mapErr) {
|
|
596
|
+
// If mapping fails, rethrow a generic HttpClientError with minimal context
|
|
597
|
+
const { HttpClientError } = require("../../errors/http-client-error");
|
|
598
|
+
const fallback = new HttpClientError(
|
|
599
|
+
(processedError && (processedError as any).message) || 'HTTP client error',
|
|
600
|
+
(processedError && (processedError as any).status) || 502,
|
|
601
|
+
(processedError && (processedError as any).code) || undefined,
|
|
602
|
+
{ original: String(processedError) },
|
|
603
|
+
);
|
|
604
|
+
throw fallback;
|
|
605
|
+
}
|
|
588
606
|
}
|
|
589
607
|
}
|
|
590
608
|
|