@technomoron/apicore-client 1.0.0-beta.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Bjørn Erik Jacobsen / Technomoron
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
13
+ all 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
20
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21
+ IN THE SOFTWARE.
@@ -0,0 +1,186 @@
1
+ /**
2
+ * Copyright (c) 2025 Bjørn Erik Jacobsen / Technomoron
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ export type maybeFile = File | Blob | [string, File | Blob];
8
+ type JsonPrimitive = string | number | boolean | null;
9
+ type JsonValue = JsonPrimitive | JsonValue[] | {
10
+ [key: string]: JsonValue;
11
+ };
12
+ type SerializableBody = JsonValue;
13
+ export interface ApiResponseData<T = unknown> {
14
+ success: boolean;
15
+ code: number;
16
+ message: string;
17
+ data: T | null;
18
+ errors: Record<string, string>;
19
+ }
20
+ export type SafeUser = Record<string, unknown>;
21
+ export type AuthIdentifier = string | number;
22
+ export interface PingResponseData {
23
+ success: boolean;
24
+ status: string;
25
+ apiVersion: string;
26
+ minClientVersion: string;
27
+ uptimeSec: number;
28
+ startedAt: string;
29
+ timestamp: string;
30
+ }
31
+ export interface ApiClientConfig {
32
+ apiKey?: string | null;
33
+ timeout?: number;
34
+ maxRetries?: number;
35
+ debug?: boolean;
36
+ enableTokens?: boolean;
37
+ }
38
+ /**
39
+ * Authentication token response shape
40
+ */
41
+ export interface AuthTokenData<User = SafeUser> {
42
+ accessToken?: string;
43
+ refreshToken?: string;
44
+ user?: User;
45
+ }
46
+ export interface WhoAmIResponseData<User = SafeUser, UserId extends AuthIdentifier = AuthIdentifier> {
47
+ user: User;
48
+ isImpersonating: boolean;
49
+ realUser?: User | null;
50
+ realUserId?: UserId | null;
51
+ }
52
+ export interface LogoutResponseData {
53
+ revoked: number;
54
+ }
55
+ export declare class ApiResponse<T = unknown> implements ApiResponseData<T> {
56
+ success: boolean;
57
+ code: number;
58
+ message: string;
59
+ data: T | null;
60
+ errors: Record<string, string>;
61
+ constructor(response?: Partial<ApiResponseData<T>>);
62
+ /**
63
+ * Creates a successful response with the provided data
64
+ * @param {T} data - The response data
65
+ * @param {Partial<ApiResponseData<T>>} overrides - Optional overrides for response properties
66
+ * @returns {ApiResponse<T>} A configured successful response
67
+ */
68
+ static ok<T>(data: T, overrides?: Partial<Omit<ApiResponseData<T>, 'data'>>): ApiResponse<T>;
69
+ /**
70
+ * Creates an error response with the provided message
71
+ * @param {unknown} messageOrError - The error message, error object, or existing ApiResponse
72
+ * @param {Partial<ApiResponseData<T>>} overrides - Optional overrides for response properties
73
+ * @returns {ApiResponse<T>} A configured error response
74
+ */
75
+ static error<T>(messageOrError: unknown, overrides?: Partial<Omit<ApiResponseData<T>, 'data'>>): ApiResponse<T>;
76
+ /**
77
+ * Adds a named error to the errors collection
78
+ * @param {string} name - The name/key for the error
79
+ * @param {string} value - The error message
80
+ */
81
+ addError(name: string, value: string): void;
82
+ /**
83
+ * Type guard to check if the response is successful and contains data
84
+ * When this returns true, TypeScript narrows the type to ensure data is not null
85
+ * @returns {boolean} True if the response is successful and contains data
86
+ */
87
+ isSuccess(): this is ApiResponse<T> & {
88
+ data: T;
89
+ };
90
+ }
91
+ declare class ApiClient {
92
+ private apiKey;
93
+ private aToken;
94
+ private rToken;
95
+ private apiUrl;
96
+ private _refreshPromise;
97
+ private timeoutMs;
98
+ private maxRetries;
99
+ private debug;
100
+ private tokens;
101
+ constructor(apiUrl: string, config?: ApiClientConfig);
102
+ /**
103
+ * Updates the client configuration
104
+ * @param {Partial<ApiClientConfig>} config - Configuration updates
105
+ */
106
+ configure(config: Partial<ApiClientConfig>): void;
107
+ /**
108
+ * Gets the current configuration
109
+ * @returns {ApiClientConfig} Current configuration
110
+ */
111
+ getConfig(): ApiClientConfig;
112
+ private tryStringify;
113
+ /**
114
+ * Retrieves the stored access token
115
+ * Designed to be overridden in subclasses for custom token storage
116
+ * @returns {string|null} The current access token or null if not set
117
+ */
118
+ get_access_token(): string | null;
119
+ /**
120
+ * Stores the access token
121
+ * Designed to be overridden in subclasses for custom token storage
122
+ * @param {string|null} access - The access token to store, or null to clear
123
+ */
124
+ set_access_token(access: string | null): void;
125
+ /**
126
+ * Retrieves the stored refresh token
127
+ * Designed to be overridden in subclasses for custom token storage
128
+ * @returns {string|null} The current refresh token or null if not set
129
+ */
130
+ get_refresh_token(): string | null;
131
+ /**
132
+ * Stores the refresh token
133
+ * Designed to be overridden in subclasses for custom token storage
134
+ * @param {string|null} refresh - The refresh token to store, or null to clear
135
+ */
136
+ set_refresh_token(refresh: string | null): void;
137
+ /**
138
+ * Sets the API key for authentication
139
+ * Designed to be overridden in subclasses for custom API key storage
140
+ * @param {string|null} apikey - The API key to use for authentication, or null to clear
141
+ */
142
+ set_apikey(apikey: string | null): void;
143
+ /**
144
+ * Retrieves the stored API key
145
+ * Designed to be overridden in subclasses for custom API key storage
146
+ * @returns {string|null} The current API key or null if not set
147
+ */
148
+ get_apikey(): string | null;
149
+ /**
150
+ * Builds authentication headers based on current configuration
151
+ * @returns {Record<string, string>} Headers object with authentication if available
152
+ */
153
+ private buildAuthHeaders;
154
+ /**
155
+ * A drop‑in replacement for fetch() that handles timeouts and
156
+ * normalized network errors and throws an ApiResponse on failure.
157
+ * Uses the instance's configured timeout value.
158
+ */
159
+ private safeFetch;
160
+ /**
161
+ * Safely parses JSON response with proper error handling
162
+ * @param {Response} response - The fetch response
163
+ * @returns {Promise<RawApiResponse<T>>} The parsed JSON data
164
+ */
165
+ private parseJsonResponse;
166
+ login<T = AuthTokenData>(username: string, password: string, domain?: string, fingerprint?: string): Promise<ApiResponse<T>>;
167
+ logout<T = LogoutResponseData>(token?: string): Promise<ApiResponse<T>>;
168
+ private refreshAccessToken;
169
+ private performRefresh;
170
+ private fetchWithRetry;
171
+ /**
172
+ * Performs a generic HTTP request to the API
173
+ * @param {'GET'|'POST'|'PUT'|'DELETE'} method - The HTTP method to use
174
+ * @param {string} command - The API endpoint path
175
+ * @param {SerializableBody} [body] - Optional request body (for POST/PUT/DELETE requests)
176
+ * @returns {Promise<ApiResponse<T>>} A promise resolving to the API response
177
+ * @template T - The expected type of the response data
178
+ */
179
+ request<T>(method: 'GET' | 'POST' | 'PUT' | 'DELETE', command: string, body?: SerializableBody, files?: maybeFile[]): Promise<ApiResponse<T>>;
180
+ get<T>(command: string): Promise<ApiResponse<T>>;
181
+ post<T>(command: string, body?: SerializableBody, files?: maybeFile[]): Promise<ApiResponse<T>>;
182
+ put<T>(command: string, body?: SerializableBody): Promise<ApiResponse<T>>;
183
+ delete<T>(command: string, body?: SerializableBody): Promise<ApiResponse<T>>;
184
+ ping(): Promise<ApiResponse<PingResponseData>>;
185
+ }
186
+ export default ApiClient;