@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/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
+ };
@@ -0,0 +1,6 @@
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
+ export {};
@@ -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,6 @@
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
+ export {};
@@ -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
+ };
@@ -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;