@nu-art/http-client 0.401.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/core/HttpClient.d.ts +92 -0
- package/core/HttpClient.js +157 -0
- package/core/HttpRequest.d.ts +205 -0
- package/core/HttpRequest.js +494 -0
- package/exceptions/HttpException.d.ts +79 -0
- package/exceptions/HttpException.js +99 -0
- package/index.d.ts +8 -0
- package/index.js +17 -0
- package/package.json +62 -0
- package/types/api-types.d.ts +142 -0
- package/types/api-types.js +21 -0
- package/types/error-types.d.ts +46 -0
- package/types/error-types.js +6 -0
- package/types/types.d.ts +26 -0
- package/types/types.js +6 -0
- package/utils/http-codes.d.ts +197 -0
- package/utils/http-codes.js +125 -0
- package/utils/utils.d.ts +42 -0
- package/utils/utils.js +75 -0
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nu-art/http-client",
|
|
3
|
+
"version": "0.401.1",
|
|
4
|
+
"description": "Type-safe HTTP client with fluent API, comprehensive logging, and request/response type safety",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"TacB0sS",
|
|
7
|
+
"http",
|
|
8
|
+
"client",
|
|
9
|
+
"axios",
|
|
10
|
+
"typescript",
|
|
11
|
+
"type-safe",
|
|
12
|
+
"api",
|
|
13
|
+
"request",
|
|
14
|
+
"response",
|
|
15
|
+
"infra",
|
|
16
|
+
"nu-art",
|
|
17
|
+
"thunderstorm"
|
|
18
|
+
],
|
|
19
|
+
"homepage": "https://github.com/nu-art-js/thunderstorm",
|
|
20
|
+
"bugs": {
|
|
21
|
+
"url": "https://github.com/nu-art-js/thunderstorm/issues"
|
|
22
|
+
},
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "git+ssh://git@github.com:nu-art-js/thunderstorm.git"
|
|
26
|
+
},
|
|
27
|
+
"license": "Apache-2.0",
|
|
28
|
+
"author": "TacB0sS",
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsc"
|
|
31
|
+
},
|
|
32
|
+
"contributors": [
|
|
33
|
+
{
|
|
34
|
+
"name": "TacB0sS"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"name": "Cipher",
|
|
38
|
+
"url": "https://www.linkedin.com/in/itay-leybovich-470b87229/"
|
|
39
|
+
}
|
|
40
|
+
],
|
|
41
|
+
"publishConfig": {
|
|
42
|
+
"directory": "dist",
|
|
43
|
+
"linkDirectory": true
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"@nu-art/ts-common": "0.401.1",
|
|
47
|
+
"axios": "^1.13.1"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@nu-art/testalot": "0.401.1"
|
|
51
|
+
},
|
|
52
|
+
"unitConfig": {
|
|
53
|
+
"type": "typescript-lib"
|
|
54
|
+
},
|
|
55
|
+
"type": "module",
|
|
56
|
+
"exports": {
|
|
57
|
+
".": {
|
|
58
|
+
"types": "./index.d.ts",
|
|
59
|
+
"import": "./index.js"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import type { HttpRequest } from '../core/HttpRequest.js';
|
|
2
|
+
import type { ResponseError } from './error-types.js';
|
|
3
|
+
import type { QueryParams } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* HTTP method enumeration.
|
|
6
|
+
*
|
|
7
|
+
* Standard HTTP methods supported by the client.
|
|
8
|
+
*/
|
|
9
|
+
export declare enum HttpMethod {
|
|
10
|
+
ALL = "all",
|
|
11
|
+
POST = "post",
|
|
12
|
+
GET = "get",
|
|
13
|
+
PATCH = "patch",
|
|
14
|
+
DELETE = "delete",
|
|
15
|
+
PUT = "put",
|
|
16
|
+
OPTIONS = "options",
|
|
17
|
+
HEAD = "head"
|
|
18
|
+
}
|
|
19
|
+
/** HTTP methods that use query parameters (no request body) */
|
|
20
|
+
export type HttpMethod_Query = 'get' | 'delete';
|
|
21
|
+
/** HTTP methods that use request body */
|
|
22
|
+
export type HttpMethod_Body = 'post' | 'put' | 'patch';
|
|
23
|
+
/** HTTP methods with no parameters or body */
|
|
24
|
+
export type HttpMethod_Empty = 'options' | 'head';
|
|
25
|
+
/**
|
|
26
|
+
* Type-safe API definition with full type information for requests and responses.
|
|
27
|
+
*
|
|
28
|
+
* Provides compile-time type safety for HTTP API calls, ensuring request bodies,
|
|
29
|
+
* query parameters, and responses match their declared types.
|
|
30
|
+
*
|
|
31
|
+
* @template M - HTTP method (string literal)
|
|
32
|
+
* @template R - Response type
|
|
33
|
+
* @template B - Body type (internal representation)
|
|
34
|
+
* @template P - Query parameters type
|
|
35
|
+
* @template IB - Input body type (what callers provide, defaults to B)
|
|
36
|
+
* @template IP - Input params type (what callers provide, defaults to P)
|
|
37
|
+
* @template E - Error response type
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* type MyApi = TypedApi<'post', {id: string}, {name: string}, {filter: string}, {name: string}, {filter: string}>;
|
|
42
|
+
* // Method: POST
|
|
43
|
+
* // Response: {id: string}
|
|
44
|
+
* // Body: {name: string}
|
|
45
|
+
* // Params: {filter: string}
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export type TypedApi<M extends string, R, B, P extends QueryParams | undefined, IB = B, IP = P, E extends ResponseError = ResponseError> = {
|
|
49
|
+
Method: M;
|
|
50
|
+
Response: R;
|
|
51
|
+
Body: B;
|
|
52
|
+
Params: P;
|
|
53
|
+
InternalParams: IP;
|
|
54
|
+
InternalBody: IB;
|
|
55
|
+
Error: E;
|
|
56
|
+
M: M;
|
|
57
|
+
R: R;
|
|
58
|
+
B: B;
|
|
59
|
+
P: P;
|
|
60
|
+
IP: IP;
|
|
61
|
+
IB: IB;
|
|
62
|
+
E: E;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Convenience type for APIs that use request bodies (POST, PUT, PATCH).
|
|
66
|
+
*
|
|
67
|
+
* @template R - Response type
|
|
68
|
+
* @template B - Body type
|
|
69
|
+
* @template IB - Input body type (defaults to B)
|
|
70
|
+
* @template E - Error type
|
|
71
|
+
* @template M - HTTP method (defaults to POST)
|
|
72
|
+
* @template P - Query params type (defaults to never)
|
|
73
|
+
*/
|
|
74
|
+
export type BodyApi<R, B, IB = B, E extends ResponseError = ResponseError, M extends HttpMethod_Body = HttpMethod.POST, P extends QueryParams = never> = TypedApi<M, R, B, P, IB, P, E>;
|
|
75
|
+
/**
|
|
76
|
+
* Convenience type for APIs that use query parameters (GET, DELETE).
|
|
77
|
+
*
|
|
78
|
+
* @template R - Response type
|
|
79
|
+
* @template P - Query params type
|
|
80
|
+
* @template E - Error type
|
|
81
|
+
* @template IP - Input params type (defaults to P)
|
|
82
|
+
* @template M - HTTP method (defaults to GET)
|
|
83
|
+
* @template B - Body type (defaults to never)
|
|
84
|
+
*/
|
|
85
|
+
export type QueryApi<R, P extends QueryParams | undefined = QueryParams, E extends ResponseError = ResponseError, IP = P, M extends HttpMethod_Query = HttpMethod.GET, B = never> = TypedApi<M, R, B, P, B, IP, E>;
|
|
86
|
+
/**
|
|
87
|
+
* Convenience type for APIs with no parameters or body (OPTIONS, HEAD).
|
|
88
|
+
*
|
|
89
|
+
* @template R - Response type
|
|
90
|
+
* @template M - HTTP method (must be OPTIONS or HEAD)
|
|
91
|
+
* @template E - Error type
|
|
92
|
+
* @template P - Query params type (defaults to never)
|
|
93
|
+
* @template B - Body type (defaults to never)
|
|
94
|
+
*/
|
|
95
|
+
export type EmptyApi<R, M extends HttpMethod_Empty, E extends ResponseError = ResponseError, P extends QueryParams = never, B = never> = TypedApi<M, R, B, P, B, P, E>;
|
|
96
|
+
/**
|
|
97
|
+
* API definition for creating requests.
|
|
98
|
+
*
|
|
99
|
+
* Specifies the HTTP method, URL configuration, and optional timeout.
|
|
100
|
+
* Either `fullUrl` (absolute) or `baseUrl` + `path` (relative) must be provided.
|
|
101
|
+
*
|
|
102
|
+
* @template API - Typed API definition
|
|
103
|
+
*/
|
|
104
|
+
export type ApiDef<API extends TypedApi<any, any, any, any, any>> = {
|
|
105
|
+
method: API['Method'];
|
|
106
|
+
fullUrl?: string;
|
|
107
|
+
baseUrl?: string;
|
|
108
|
+
path: string;
|
|
109
|
+
timeout?: number;
|
|
110
|
+
errors?: API['Error']['type'];
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* Recursive API structure type for organizing APIs into namespaces.
|
|
114
|
+
*
|
|
115
|
+
* Allows nesting APIs in a hierarchical structure, where each level can contain
|
|
116
|
+
* either a TypedApi or another ApiStruct (sub-namespace).
|
|
117
|
+
*/
|
|
118
|
+
export type ApiStruct = {
|
|
119
|
+
[k: string]: (TypedApi<any, any, any, any, any> | ApiStruct);
|
|
120
|
+
};
|
|
121
|
+
export type ApiDefResolver<API_Struct extends ApiStruct> = API_Struct extends TypedApi<any, any, any, any, any> ? ApiDef<API_Struct> : API_Struct extends ApiStruct ? ApiDefRouter<API_Struct> : never;
|
|
122
|
+
export type ApiDefRouter<API_Struct extends ApiStruct> = {
|
|
123
|
+
[P in keyof API_Struct]: ApiDefResolver<API_Struct[P]>;
|
|
124
|
+
};
|
|
125
|
+
export type ApiDefCaller<API_Struct extends ApiStruct> = API_Struct extends TypedApi<any, any, any, any, any> ? ApiCaller<API_Struct> : API_Struct extends ApiStruct ? ApiCallerRouter<API_Struct> : never;
|
|
126
|
+
export type ApiCallerRouter<API_Struct extends ApiStruct> = {
|
|
127
|
+
[P in keyof API_Struct]: ApiDefCaller<API_Struct[P]>;
|
|
128
|
+
};
|
|
129
|
+
export type ApiCaller_Query<API extends QueryApi<any, any, any, any, HttpMethod_Query>> = API['IP'] extends undefined ? () => HttpRequest<API> : (query: API['IP']) => HttpRequest<API>;
|
|
130
|
+
export type ApiCaller_Body<API extends BodyApi<any, any, any, any, HttpMethod_Body>> = API['IB'] extends undefined ? () => HttpRequest<API> : (query: API['IB']) => HttpRequest<API>;
|
|
131
|
+
export type ApiCaller_Any<API extends TypedApi<any, any, any, any, any>> = (body: API['IB'], query: API['IP']) => HttpRequest<API>;
|
|
132
|
+
/**
|
|
133
|
+
* Resolves the appropriate caller function type based on API method.
|
|
134
|
+
*
|
|
135
|
+
* Automatically selects the correct function signature:
|
|
136
|
+
* - QueryApi → function(query?) → HttpRequest
|
|
137
|
+
* - BodyApi → function(body?) → HttpRequest
|
|
138
|
+
* - Other → function(body, query) → HttpRequest
|
|
139
|
+
*
|
|
140
|
+
* @template API - Typed API definition
|
|
141
|
+
*/
|
|
142
|
+
export type ApiCaller<API> = API extends QueryApi<any, any, any, any, HttpMethod_Query> ? ApiCaller_Query<API> : API extends BodyApi<any, any, any, any, HttpMethod_Body> ? ApiCaller_Body<API> : API extends TypedApi<any, any, any, any, any> ? ApiCaller_Any<API> : never;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @nu-art/thunderstorm-http - A robust and type-safe HTTP client for Thunderstorm applications
|
|
3
|
+
* Copyright (C) 2024 Adam van der Kruk aka TacB0sS
|
|
4
|
+
* Licensed under the Apache License, Version 2.0
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* HTTP method enumeration.
|
|
8
|
+
*
|
|
9
|
+
* Standard HTTP methods supported by the client.
|
|
10
|
+
*/
|
|
11
|
+
export var HttpMethod;
|
|
12
|
+
(function (HttpMethod) {
|
|
13
|
+
HttpMethod["ALL"] = "all";
|
|
14
|
+
HttpMethod["POST"] = "post";
|
|
15
|
+
HttpMethod["GET"] = "get";
|
|
16
|
+
HttpMethod["PATCH"] = "patch";
|
|
17
|
+
HttpMethod["DELETE"] = "delete";
|
|
18
|
+
HttpMethod["PUT"] = "put";
|
|
19
|
+
HttpMethod["OPTIONS"] = "options";
|
|
20
|
+
HttpMethod["HEAD"] = "head";
|
|
21
|
+
})(HttpMethod || (HttpMethod = {}));
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic response error type for API error handling.
|
|
3
|
+
*
|
|
4
|
+
* @template K - Error type identifier (string literal)
|
|
5
|
+
* @template Data - Error data payload
|
|
6
|
+
*/
|
|
7
|
+
export type ResponseError<K extends string = string, Data = any> = {
|
|
8
|
+
/** Error type identifier */
|
|
9
|
+
type: K;
|
|
10
|
+
/** Error data payload */
|
|
11
|
+
data: Data;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Standard error message response type.
|
|
15
|
+
*
|
|
16
|
+
* Used for general error messages in API responses.
|
|
17
|
+
*/
|
|
18
|
+
export type ApiError_GeneralErrorMessage = ResponseError<'error-message', {
|
|
19
|
+
message: string;
|
|
20
|
+
}>;
|
|
21
|
+
/**
|
|
22
|
+
* API error response structure.
|
|
23
|
+
*
|
|
24
|
+
* Contains an optional debug message (for developers) and an optional
|
|
25
|
+
* structured error object (for clients).
|
|
26
|
+
*
|
|
27
|
+
* @template E - Response error type
|
|
28
|
+
*/
|
|
29
|
+
export type ApiErrorResponse<E extends ResponseError> = {
|
|
30
|
+
/** Optional debug message (typically includes stack traces, internal details) */
|
|
31
|
+
debugMessage?: string;
|
|
32
|
+
/** Optional structured error object */
|
|
33
|
+
error?: E;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Progress event type for upload/download tracking.
|
|
37
|
+
*
|
|
38
|
+
* Mirrors the ProgressEvent interface for compatibility with XMLHttpRequest
|
|
39
|
+
* and fetch progress events.
|
|
40
|
+
*/
|
|
41
|
+
export type TS_Progress = {
|
|
42
|
+
readonly lengthComputable: boolean;
|
|
43
|
+
readonly loaded: number;
|
|
44
|
+
readonly target: any;
|
|
45
|
+
readonly total: number;
|
|
46
|
+
};
|
package/types/types.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type for route/query parameters with dynamic value support.
|
|
3
|
+
*
|
|
4
|
+
* Supports static values (string, number, boolean) or functions that return values.
|
|
5
|
+
* Functions are evaluated when composing the query string, allowing dynamic
|
|
6
|
+
* parameter generation (e.g., timestamps, IDs).
|
|
7
|
+
*/
|
|
8
|
+
export type RouteParams = {
|
|
9
|
+
[key: string]: string | number | boolean | undefined | (() => string | number);
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Static query parameters type (no functions).
|
|
13
|
+
*
|
|
14
|
+
* Used for API type definitions where parameters are known at compile time.
|
|
15
|
+
*/
|
|
16
|
+
export type QueryParams = {
|
|
17
|
+
[key: string]: string | number | boolean | undefined;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* URL query parameters with string values only.
|
|
21
|
+
*
|
|
22
|
+
* Used for URL composition where all values must be strings.
|
|
23
|
+
*/
|
|
24
|
+
export type UrlQueryParams = {
|
|
25
|
+
[key: string]: string | undefined;
|
|
26
|
+
};
|
package/types/types.js
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { ApiError_GeneralErrorMessage } from '../types/error-types.js';
|
|
2
|
+
import { ApiException } from '../exceptions/HttpException.js';
|
|
3
|
+
/**
|
|
4
|
+
* HTTP status code constants organized by status class.
|
|
5
|
+
*
|
|
6
|
+
* Provides:
|
|
7
|
+
* - Standard HTTP status codes (1XX, 2XX, 3XX, 4XX, 5XX)
|
|
8
|
+
* - Custom status codes (459-463, 490, 555, 560-561, 598-599)
|
|
9
|
+
* - Factory functions for 4XX and 5XX errors that create ApiException instances
|
|
10
|
+
*
|
|
11
|
+
* **Usage**:
|
|
12
|
+
* - For errors: `throw HttpCodes._4XX.NOT_FOUND('User not found', 'User ID: 123')`
|
|
13
|
+
* - For status codes: `HttpCodes._2XX.OK` (returns 200)
|
|
14
|
+
*
|
|
15
|
+
* **Note**: 4XX and 5XX codes are functions that create exceptions, while
|
|
16
|
+
* 1XX, 2XX, and 3XX are just numeric constants.
|
|
17
|
+
*/
|
|
18
|
+
export declare const HttpCodes: {
|
|
19
|
+
readonly _1XX: {
|
|
20
|
+
readonly CONTINUE: 100;
|
|
21
|
+
readonly SWITCHING_PROTOCOLS: 101;
|
|
22
|
+
readonly PROCESSING: 102;
|
|
23
|
+
readonly EARLY_HINTS: 103;
|
|
24
|
+
};
|
|
25
|
+
readonly _2XX: {
|
|
26
|
+
readonly OK: 200;
|
|
27
|
+
readonly CREATED: 201;
|
|
28
|
+
readonly ACCEPTED: 202;
|
|
29
|
+
readonly NON_AUTHORITATIVE_INFORMATION: 203;
|
|
30
|
+
readonly NO_CONTENT: 204;
|
|
31
|
+
readonly RESET_CONTENT: 205;
|
|
32
|
+
readonly PARTIAL_CONTENT: 206;
|
|
33
|
+
readonly MULTI_STATUS: 207;
|
|
34
|
+
readonly ALREADY_REPORTED: 208;
|
|
35
|
+
readonly IM_USED: 226;
|
|
36
|
+
};
|
|
37
|
+
readonly _3XX: {
|
|
38
|
+
readonly MULTIPLE_CHOICES: 300;
|
|
39
|
+
readonly MOVED_PERMANENTLY: 301;
|
|
40
|
+
readonly FOUND: 302;
|
|
41
|
+
readonly SEE_OTHER: 303;
|
|
42
|
+
readonly NOT_MODIFIED: 304;
|
|
43
|
+
readonly USE_PROXY: 305;
|
|
44
|
+
readonly TEMPORARY_REDIRECT: 307;
|
|
45
|
+
readonly PERMANENT_REDIRECT: 308;
|
|
46
|
+
};
|
|
47
|
+
readonly _4XX: {
|
|
48
|
+
readonly BAD_REQUEST: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
49
|
+
code: number;
|
|
50
|
+
};
|
|
51
|
+
readonly UNAUTHORIZED: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
52
|
+
code: number;
|
|
53
|
+
};
|
|
54
|
+
readonly PAYMENT_REQUIRED: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
55
|
+
code: number;
|
|
56
|
+
};
|
|
57
|
+
readonly FORBIDDEN: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
58
|
+
code: number;
|
|
59
|
+
};
|
|
60
|
+
readonly NOT_FOUND: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
61
|
+
code: number;
|
|
62
|
+
};
|
|
63
|
+
readonly METHOD_NOT_ALLOWED: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
64
|
+
code: number;
|
|
65
|
+
};
|
|
66
|
+
readonly NOT_ACCEPTABLE: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
67
|
+
code: number;
|
|
68
|
+
};
|
|
69
|
+
readonly PROXY_AUTHENTICATION_REQUIRED: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
70
|
+
code: number;
|
|
71
|
+
};
|
|
72
|
+
readonly REQUEST_TIMEOUT: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
73
|
+
code: number;
|
|
74
|
+
};
|
|
75
|
+
readonly CONFLICT: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
76
|
+
code: number;
|
|
77
|
+
};
|
|
78
|
+
readonly GONE: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
79
|
+
code: number;
|
|
80
|
+
};
|
|
81
|
+
readonly LENGTH_REQUIRED: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
82
|
+
code: number;
|
|
83
|
+
};
|
|
84
|
+
readonly PRECONDITION_FAILED: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
85
|
+
code: number;
|
|
86
|
+
};
|
|
87
|
+
readonly PAYLOAD_TOO_LARGE: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
88
|
+
code: number;
|
|
89
|
+
};
|
|
90
|
+
readonly URI_TOO_LONG: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
91
|
+
code: number;
|
|
92
|
+
};
|
|
93
|
+
readonly UNSUPPORTED_MEDIA_TYPE: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
94
|
+
code: number;
|
|
95
|
+
};
|
|
96
|
+
readonly RANGE_NOT_SATISFIABLE: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
97
|
+
code: number;
|
|
98
|
+
};
|
|
99
|
+
readonly EXPECTATION_FAILED: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
100
|
+
code: number;
|
|
101
|
+
};
|
|
102
|
+
readonly IM_A_TEAPOT: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
103
|
+
code: number;
|
|
104
|
+
};
|
|
105
|
+
readonly FAILED_VALIDATION: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
106
|
+
code: number;
|
|
107
|
+
};
|
|
108
|
+
readonly MISDIRECTED_REQUEST: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
109
|
+
code: number;
|
|
110
|
+
};
|
|
111
|
+
readonly UNPROCESSABLE_ENTITY: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
112
|
+
code: number;
|
|
113
|
+
};
|
|
114
|
+
readonly LOCKED: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
115
|
+
code: number;
|
|
116
|
+
};
|
|
117
|
+
readonly FAILED_DEPENDENCY: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
118
|
+
code: number;
|
|
119
|
+
};
|
|
120
|
+
readonly TOO_EARLY: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
121
|
+
code: number;
|
|
122
|
+
};
|
|
123
|
+
readonly UPGRADE_REQUIRED: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
124
|
+
code: number;
|
|
125
|
+
};
|
|
126
|
+
readonly PRECONDITION_REQUIRED: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
127
|
+
code: number;
|
|
128
|
+
};
|
|
129
|
+
readonly TOO_MANY_REQUESTS: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
130
|
+
code: number;
|
|
131
|
+
};
|
|
132
|
+
readonly REQUEST_HEADER_FIELDS_TOO_LARGE: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
133
|
+
code: number;
|
|
134
|
+
};
|
|
135
|
+
readonly UNAVAILABLE_FOR_LEGAL_REASONS: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
136
|
+
code: number;
|
|
137
|
+
};
|
|
138
|
+
readonly ENTITY_MISSING: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
139
|
+
code: number;
|
|
140
|
+
};
|
|
141
|
+
readonly ENTITY_ALREADY_EXISTS: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
142
|
+
code: number;
|
|
143
|
+
};
|
|
144
|
+
readonly ENTITY_IS_OUTDATED: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
145
|
+
code: number;
|
|
146
|
+
};
|
|
147
|
+
readonly INTERNAL_MISMATCH: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
148
|
+
code: number;
|
|
149
|
+
};
|
|
150
|
+
readonly ENTITY_DOESNT_EXISTS: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
151
|
+
code: number;
|
|
152
|
+
};
|
|
153
|
+
readonly OPERATION_FAILED: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
154
|
+
code: number;
|
|
155
|
+
};
|
|
156
|
+
};
|
|
157
|
+
readonly _5XX: {
|
|
158
|
+
readonly INTERNAL_SERVER_ERROR: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
159
|
+
code: number;
|
|
160
|
+
};
|
|
161
|
+
readonly NOT_IMPLEMENTED: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
162
|
+
code: number;
|
|
163
|
+
};
|
|
164
|
+
readonly BAD_GATEWAY: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
165
|
+
code: number;
|
|
166
|
+
};
|
|
167
|
+
readonly SERVICE_UNAVAILABLE: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
168
|
+
code: number;
|
|
169
|
+
};
|
|
170
|
+
readonly GATEWAY_TIMEOUT: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
171
|
+
code: number;
|
|
172
|
+
};
|
|
173
|
+
readonly HTTP_VERSION_NOT_SUPPORTED: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
174
|
+
code: number;
|
|
175
|
+
};
|
|
176
|
+
readonly VARIANT_ALSO_NEGOTIATES: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
177
|
+
code: number;
|
|
178
|
+
};
|
|
179
|
+
readonly INSUFFICIENT_STORAGE: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
180
|
+
code: number;
|
|
181
|
+
};
|
|
182
|
+
readonly LOOP_DETECTED: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
183
|
+
code: number;
|
|
184
|
+
};
|
|
185
|
+
readonly NOT_EXTENDED: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
186
|
+
code: number;
|
|
187
|
+
};
|
|
188
|
+
readonly NETWORK_AUTHENTICATION_REQUIRED: ((userMessage: string, debugMessage?: string, cause?: Error) => ApiException<ApiError_GeneralErrorMessage>) & {
|
|
189
|
+
code: number;
|
|
190
|
+
};
|
|
191
|
+
readonly DEBUG_WHO_CALLED_THIS: 555;
|
|
192
|
+
readonly BAD_IMPLEMENTATION: 560;
|
|
193
|
+
readonly IMPLEMENTATION_MISSING: 561;
|
|
194
|
+
readonly SHOULD_NOT_HAPPENED: 598;
|
|
195
|
+
readonly MUST_NEVER_HAPPENED: 599;
|
|
196
|
+
};
|
|
197
|
+
};
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @nu-art/thunderstorm-http - A robust and type-safe HTTP client for Thunderstorm applications
|
|
3
|
+
* Copyright (C) 2024 Adam van der Kruk aka TacB0sS
|
|
4
|
+
* Licensed under the Apache License, Version 2.0
|
|
5
|
+
*/
|
|
6
|
+
import { ApiException } from '../exceptions/HttpException.js';
|
|
7
|
+
/**
|
|
8
|
+
* Creates a factory function for HTTP error exceptions.
|
|
9
|
+
*
|
|
10
|
+
* Returns a function that creates an ApiException with the specified HTTP status code.
|
|
11
|
+
* The function also has a `code` property for accessing the status code.
|
|
12
|
+
*
|
|
13
|
+
* @param code - HTTP status code
|
|
14
|
+
* @returns Function that creates ApiException instances, with a `code` property
|
|
15
|
+
*/
|
|
16
|
+
function createGeneralError(code) {
|
|
17
|
+
const errorFunction = (userMessage, debugMessage = userMessage, cause) => new ApiException(code, debugMessage, cause).setErrorBody({
|
|
18
|
+
type: 'error-message',
|
|
19
|
+
data: { message: userMessage }
|
|
20
|
+
});
|
|
21
|
+
return Object.assign(errorFunction, { code });
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* HTTP status code constants organized by status class.
|
|
25
|
+
*
|
|
26
|
+
* Provides:
|
|
27
|
+
* - Standard HTTP status codes (1XX, 2XX, 3XX, 4XX, 5XX)
|
|
28
|
+
* - Custom status codes (459-463, 490, 555, 560-561, 598-599)
|
|
29
|
+
* - Factory functions for 4XX and 5XX errors that create ApiException instances
|
|
30
|
+
*
|
|
31
|
+
* **Usage**:
|
|
32
|
+
* - For errors: `throw HttpCodes._4XX.NOT_FOUND('User not found', 'User ID: 123')`
|
|
33
|
+
* - For status codes: `HttpCodes._2XX.OK` (returns 200)
|
|
34
|
+
*
|
|
35
|
+
* **Note**: 4XX and 5XX codes are functions that create exceptions, while
|
|
36
|
+
* 1XX, 2XX, and 3XX are just numeric constants.
|
|
37
|
+
*/
|
|
38
|
+
export const HttpCodes = {
|
|
39
|
+
_1XX: {
|
|
40
|
+
CONTINUE: 100,
|
|
41
|
+
SWITCHING_PROTOCOLS: 101,
|
|
42
|
+
PROCESSING: 102,
|
|
43
|
+
EARLY_HINTS: 103,
|
|
44
|
+
},
|
|
45
|
+
_2XX: {
|
|
46
|
+
OK: 200,
|
|
47
|
+
CREATED: 201,
|
|
48
|
+
ACCEPTED: 202,
|
|
49
|
+
NON_AUTHORITATIVE_INFORMATION: 203,
|
|
50
|
+
NO_CONTENT: 204,
|
|
51
|
+
RESET_CONTENT: 205,
|
|
52
|
+
PARTIAL_CONTENT: 206,
|
|
53
|
+
MULTI_STATUS: 207,
|
|
54
|
+
ALREADY_REPORTED: 208,
|
|
55
|
+
IM_USED: 226,
|
|
56
|
+
},
|
|
57
|
+
_3XX: {
|
|
58
|
+
MULTIPLE_CHOICES: 300,
|
|
59
|
+
MOVED_PERMANENTLY: 301,
|
|
60
|
+
FOUND: 302,
|
|
61
|
+
SEE_OTHER: 303,
|
|
62
|
+
NOT_MODIFIED: 304,
|
|
63
|
+
USE_PROXY: 305,
|
|
64
|
+
TEMPORARY_REDIRECT: 307,
|
|
65
|
+
PERMANENT_REDIRECT: 308,
|
|
66
|
+
},
|
|
67
|
+
_4XX: {
|
|
68
|
+
BAD_REQUEST: createGeneralError(400),
|
|
69
|
+
UNAUTHORIZED: createGeneralError(401),
|
|
70
|
+
PAYMENT_REQUIRED: createGeneralError(402),
|
|
71
|
+
FORBIDDEN: createGeneralError(403),
|
|
72
|
+
NOT_FOUND: createGeneralError(404),
|
|
73
|
+
METHOD_NOT_ALLOWED: createGeneralError(405),
|
|
74
|
+
NOT_ACCEPTABLE: createGeneralError(406),
|
|
75
|
+
PROXY_AUTHENTICATION_REQUIRED: createGeneralError(407),
|
|
76
|
+
REQUEST_TIMEOUT: createGeneralError(408),
|
|
77
|
+
CONFLICT: createGeneralError(409),
|
|
78
|
+
GONE: createGeneralError(410),
|
|
79
|
+
LENGTH_REQUIRED: createGeneralError(411),
|
|
80
|
+
PRECONDITION_FAILED: createGeneralError(412),
|
|
81
|
+
PAYLOAD_TOO_LARGE: createGeneralError(413),
|
|
82
|
+
URI_TOO_LONG: createGeneralError(414),
|
|
83
|
+
UNSUPPORTED_MEDIA_TYPE: createGeneralError(415),
|
|
84
|
+
RANGE_NOT_SATISFIABLE: createGeneralError(416),
|
|
85
|
+
EXPECTATION_FAILED: createGeneralError(417),
|
|
86
|
+
IM_A_TEAPOT: createGeneralError(418),
|
|
87
|
+
FAILED_VALIDATION: createGeneralError(420),
|
|
88
|
+
MISDIRECTED_REQUEST: createGeneralError(421),
|
|
89
|
+
UNPROCESSABLE_ENTITY: createGeneralError(422),
|
|
90
|
+
LOCKED: createGeneralError(423),
|
|
91
|
+
FAILED_DEPENDENCY: createGeneralError(424),
|
|
92
|
+
TOO_EARLY: createGeneralError(425),
|
|
93
|
+
UPGRADE_REQUIRED: createGeneralError(426),
|
|
94
|
+
PRECONDITION_REQUIRED: createGeneralError(428),
|
|
95
|
+
TOO_MANY_REQUESTS: createGeneralError(429),
|
|
96
|
+
REQUEST_HEADER_FIELDS_TOO_LARGE: createGeneralError(431),
|
|
97
|
+
UNAVAILABLE_FOR_LEGAL_REASONS: createGeneralError(451),
|
|
98
|
+
//custom
|
|
99
|
+
ENTITY_MISSING: createGeneralError(459),
|
|
100
|
+
ENTITY_ALREADY_EXISTS: createGeneralError(460),
|
|
101
|
+
ENTITY_IS_OUTDATED: createGeneralError(461),
|
|
102
|
+
INTERNAL_MISMATCH: createGeneralError(462),
|
|
103
|
+
ENTITY_DOESNT_EXISTS: createGeneralError(463),
|
|
104
|
+
OPERATION_FAILED: createGeneralError(490),
|
|
105
|
+
},
|
|
106
|
+
_5XX: {
|
|
107
|
+
INTERNAL_SERVER_ERROR: createGeneralError(500),
|
|
108
|
+
NOT_IMPLEMENTED: createGeneralError(501),
|
|
109
|
+
BAD_GATEWAY: createGeneralError(502),
|
|
110
|
+
SERVICE_UNAVAILABLE: createGeneralError(503),
|
|
111
|
+
GATEWAY_TIMEOUT: createGeneralError(504),
|
|
112
|
+
HTTP_VERSION_NOT_SUPPORTED: createGeneralError(505),
|
|
113
|
+
VARIANT_ALSO_NEGOTIATES: createGeneralError(506),
|
|
114
|
+
INSUFFICIENT_STORAGE: createGeneralError(507),
|
|
115
|
+
LOOP_DETECTED: createGeneralError(508),
|
|
116
|
+
NOT_EXTENDED: createGeneralError(510),
|
|
117
|
+
NETWORK_AUTHENTICATION_REQUIRED: createGeneralError(511),
|
|
118
|
+
//custom
|
|
119
|
+
DEBUG_WHO_CALLED_THIS: 555,
|
|
120
|
+
BAD_IMPLEMENTATION: 560,
|
|
121
|
+
IMPLEMENTATION_MISSING: 561,
|
|
122
|
+
SHOULD_NOT_HAPPENED: 598,
|
|
123
|
+
MUST_NEVER_HAPPENED: 599,
|
|
124
|
+
},
|
|
125
|
+
};
|
package/utils/utils.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { StringMap } from '@nu-art/ts-common';
|
|
2
|
+
import { RouteParams } from '../types/types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Composes a query string from parameters.
|
|
5
|
+
*
|
|
6
|
+
* Converts an object of parameters into a URL-encoded query string.
|
|
7
|
+
* - Functions are evaluated to get their return value
|
|
8
|
+
* - undefined/null values result in `key=` (empty value)
|
|
9
|
+
* - All values are URI-encoded
|
|
10
|
+
*
|
|
11
|
+
* @param params - Object with parameter keys and values
|
|
12
|
+
* @returns URL-encoded query string (e.g., "key1=value1&key2=value2")
|
|
13
|
+
*/
|
|
14
|
+
export declare function composeQueryParams(params?: RouteParams): string;
|
|
15
|
+
/**
|
|
16
|
+
* Composes a complete URL with query parameters and optional hash.
|
|
17
|
+
*
|
|
18
|
+
* Combines a base URL with query parameters and/or a hash fragment.
|
|
19
|
+
* Only adds query string if there are parameters. Hash is added if provided.
|
|
20
|
+
*
|
|
21
|
+
* @param url - Base URL
|
|
22
|
+
* @param params - Query parameters object
|
|
23
|
+
* @param hash - Optional hash fragment (will add '#' if not present)
|
|
24
|
+
* @returns Complete URL with query string and/or hash
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* composeUrl('/path', {foo: 'bar'}, 'section1')
|
|
29
|
+
* // Returns: '/path?foo=bar#section1'
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export declare function composeUrl(url: string, params?: RouteParams, hash?: string): string;
|
|
33
|
+
/**
|
|
34
|
+
* Encodes URL parameters into a StringMap with URI-encoded values.
|
|
35
|
+
*
|
|
36
|
+
* Similar to composeQueryParams but returns an object instead of a query string.
|
|
37
|
+
* Useful when you need the encoded parameters as a map rather than a string.
|
|
38
|
+
*
|
|
39
|
+
* @param params - Route parameters object
|
|
40
|
+
* @returns Object with URI-encoded parameter values
|
|
41
|
+
*/
|
|
42
|
+
export declare function encodeUrlParams(params?: RouteParams): StringMap;
|