apexa 0.0.0-stage → 0.1.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/CHANGELOG.md ADDED
@@ -0,0 +1,21 @@
1
+ # Changelog
2
+
3
+ All notable changes to Apexa are documented here.
4
+
5
+ This project follows [Semantic Versioning](https://semver.org/).
6
+
7
+ ## [Unreleased]
8
+
9
+ ### Added
10
+ - Class-based HTTP client API.
11
+ - Typed request and response contracts.
12
+ - Request and response interceptors.
13
+ - Per-request overrides for client configuration.
14
+ - Configurable adapters and response interpreters.
15
+ - Timeout, cancellation, CSRF, and retry options.
16
+
17
+ ### Before the first release
18
+ - Confirm the final package name and version.
19
+ - Run type checking and automated tests.
20
+ - Verify ESM exports and generated declaration files.
21
+ - Test the packed tarball in a clean consumer project.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Apexa contributors
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 CHANGED
@@ -1,3 +1,275 @@
1
- # Temporary Holding Version
1
+ # Apexa
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ **A configurable, TypeScript-first HTTP client built on the Fetch API.**
4
+
5
+ Apexa provides a small class-based API for HTTP requests, request and response interceptors, per-request configuration overrides, custom adapters, response parsing, cancellation, timeouts, CSRF handling, and opt-in retries.
6
+
7
+ > **Release status:** Review and test the implementation before publishing. The documentation and release scaffold do not certify the current source code as production-ready.
8
+
9
+ ## Features
10
+
11
+ - TypeScript-first API with generic response types.
12
+ - Instance defaults with per-request overrides, including `baseUrl` and `basePath`.
13
+ - Familiar `get`, `post`, `put`, `patch`, `delete`, `head`, `options`, and `request` methods.
14
+ - Query parameter serialization.
15
+ - JSON request-body serialization and content-type-aware response parsing.
16
+ - Request and response interceptors.
17
+ - Custom Fetch-compatible adapters and response interpreters.
18
+ - Request cancellation with `AbortSignal`.
19
+ - Request timeouts and minimum request duration.
20
+ - Optional CSRF token handling.
21
+ - Opt-in retry configuration for safe methods.
22
+ - Structured errors with stable error codes.
23
+
24
+ ## Requirements
25
+
26
+ - A supported Node.js release or a modern browser with the Fetch API.
27
+ - TypeScript 5.x or later if consuming TypeScript declarations directly.
28
+
29
+ The default Fetch adapter requires absolute URLs in environments where Fetch does not resolve relative URLs (for example, Node.js). Configure `baseUrl` or provide a custom adapter.
30
+
31
+ ## Installation
32
+
33
+ ```bash
34
+ npm install apexa
35
+ ```
36
+
37
+ If the unscoped `apexa` name is unavailable, install the published scoped name chosen by the maintainers instead.
38
+
39
+ ## Quick start
40
+
41
+ ```ts
42
+ import Apexa from "apexa";
43
+
44
+ interface User {
45
+ id: string;
46
+ name: string;
47
+ email: string;
48
+ }
49
+
50
+ const api = new Apexa({
51
+ baseUrl: "https://api.example.com",
52
+ basePath: "/api/v1",
53
+ timeout: 10_000,
54
+ headers: {
55
+ Accept: "application/json",
56
+ },
57
+ });
58
+
59
+ const response = await api.get<User>("/users/123");
60
+
61
+ console.log(response.status);
62
+ console.log(response.data.name);
63
+ ```
64
+
65
+ The generic type passed to `get<T>()` is a compile-time expectation. It does **not** validate untrusted server data at runtime. Validate API payloads with a runtime schema when that guarantee is required.
66
+
67
+ ## Override settings for one request
68
+
69
+ Request-level options override the instance defaults.
70
+
71
+ ```ts
72
+ const response = await api.get<User>("/users/123", {
73
+ baseUrl: "https://staging.example.com",
74
+ basePath: "/api/v2",
75
+ timeout: 5_000,
76
+ credentials: "same-origin",
77
+ headers: {
78
+ Authorization: "Bearer YOUR_TOKEN",
79
+ },
80
+ query: {
81
+ include: ["profile", "roles"],
82
+ active: true,
83
+ },
84
+ });
85
+ ```
86
+
87
+ An absolute URL passed as the `url` argument bypasses `baseUrl` and `basePath`.
88
+
89
+ ## Send JSON
90
+
91
+ ```ts
92
+ interface CreateUserInput {
93
+ name: string;
94
+ email: string;
95
+ }
96
+
97
+ const response = await api.post<User>("/users", {
98
+ name: "Ada Lovelace",
99
+ email: "ada@example.com",
100
+ });
101
+ ```
102
+
103
+ Plain objects and arrays are serialized as JSON by the default adapter. Use `FormData`, `Blob`, `URLSearchParams`, or another supported `BodyInit` value for non-JSON payloads. Do not manually set a multipart `Content-Type` header for `FormData`; the runtime must generate the boundary.
104
+
105
+ ## Interceptors
106
+
107
+ ```ts
108
+ const requestInterceptorId = api.interceptors.request.use((config) => {
109
+ config.headers.set("X-Client", "Apexa");
110
+ return config;
111
+ });
112
+
113
+ const responseInterceptorId = api.interceptors.response.use(
114
+ (response) => response,
115
+ (error: unknown) => {
116
+ console.error("Request failed", error);
117
+ throw error;
118
+ },
119
+ );
120
+
121
+ // Remove interceptors when no longer needed.
122
+ api.interceptors.request.eject(requestInterceptorId);
123
+ api.interceptors.response.eject(responseInterceptorId);
124
+ ```
125
+
126
+ Request interceptors execute in reverse registration order. Response interceptors execute in registration order. An interceptor should return the updated configuration or response unless it intentionally rejects the chain.
127
+
128
+ ## Error handling
129
+
130
+ ```ts
131
+ import Apexa, { ApexaError } from "apexa";
132
+
133
+ const api = new Apexa({ baseUrl: "https://api.example.com" });
134
+
135
+ try {
136
+ await api.get("/private");
137
+ } catch (error: unknown) {
138
+ if (error instanceof ApexaError) {
139
+ console.error(error.code);
140
+ console.error(error.message);
141
+ console.error(error.response?.status);
142
+ } else {
143
+ throw error;
144
+ }
145
+ }
146
+ ```
147
+
148
+ Errors may expose a stable `code`, request `config`, response metadata, and the original `cause` where available. See [API reference](./docs/API.md) for the error code list.
149
+
150
+ ## Cancellation
151
+
152
+ ```ts
153
+ const controller = new AbortController();
154
+
155
+ const request = api.get<User>("/users/123", {
156
+ signal: controller.signal,
157
+ });
158
+
159
+ // Cancel whenever appropriate.
160
+ controller.abort();
161
+
162
+ await request;
163
+ ```
164
+
165
+ The request rejects when aborted. Handle the rejection at the call site.
166
+
167
+ ## Timeout and minimum duration
168
+
169
+ ```ts
170
+ const response = await api.get<User>("/users/123", {
171
+ timeout: 8_000,
172
+ minimumTime: 250,
173
+ });
174
+ ```
175
+
176
+ `timeout: 0` disables the timeout. `minimumTime` requests that the total request operation take at least the specified number of milliseconds; it is not a server-side processing guarantee.
177
+
178
+ ## CSRF
179
+
180
+ CSRF handling is disabled by default. Enable it only when it matches the security model of your application.
181
+
182
+ ```ts
183
+ const api = new Apexa({
184
+ baseUrl: "https://app.example.com",
185
+ csrf: {
186
+ enabled: true,
187
+ cookieName: "csrf-token",
188
+ headerName: "X-CSRF-Token",
189
+ required: true,
190
+ },
191
+ });
192
+ ```
193
+
194
+ By default, the implementation looks for a readable cookie. `HttpOnly` cookies cannot be read by JavaScript; use `tokenProvider` or another server/application-specific mechanism when needed. CSRF tokens do not replace authorization, secure cookie settings, or server-side CSRF validation.
195
+
196
+ ## Retries
197
+
198
+ Retries are disabled by default. Enable them deliberately:
199
+
200
+ ```ts
201
+ const response = await api.get("/status", {
202
+ retry: {
203
+ enabled: true,
204
+ retries: 2,
205
+ delay: 300,
206
+ maxDelay: 5_000,
207
+ backoff: 2,
208
+ },
209
+ });
210
+ ```
211
+
212
+ The default adapter should retry only operations safe to repeat. Do not automatically retry non-idempotent mutations unless your API supports idempotency keys and you have deliberately designed for duplicate delivery.
213
+
214
+ ## Custom response interpreter
215
+
216
+ ```ts
217
+ const api = new Apexa({
218
+ baseUrl: "https://api.example.com",
219
+ interpreter: async (response) => {
220
+ if (response.status === 204) return undefined;
221
+ return response.json() as Promise<unknown>;
222
+ },
223
+ });
224
+ ```
225
+
226
+ The interpreter parses response data; it does not validate the returned payload's shape.
227
+
228
+ ## Custom adapter
229
+
230
+ ```ts
231
+ import type { HttpAdapter } from "apexa";
232
+
233
+ const adapter: HttpAdapter = async (config) => {
234
+ return fetch(config.url, {
235
+ method: config.method,
236
+ headers: config.headers,
237
+ signal: config.signal,
238
+ credentials: config.credentials,
239
+ });
240
+ };
241
+
242
+ const api = new Apexa({
243
+ baseUrl: "https://api.example.com",
244
+ adapter,
245
+ });
246
+ ```
247
+
248
+ A custom adapter must honor the contract expected by Apexa and return a native `Response`. If it needs to support additional HTTP methods or runtime-specific behavior, document and test those guarantees.
249
+
250
+ ## API reference
251
+
252
+ See [docs/API.md](./docs/API.md) for the public configuration, methods, interceptors, errors, and defaults.
253
+
254
+ ## Browser and server environments
255
+
256
+ - The default adapter uses the platform Fetch API.
257
+ - Cookie-based CSRF token lookup requires a browser environment with `document.cookie`.
258
+ - Browser CORS rules and server-side networking restrictions still apply.
259
+ - In Node.js, set an absolute `baseUrl` for relative endpoint paths.
260
+ - Do not put secrets in client-side bundles or request metadata.
261
+
262
+ ## Development
263
+
264
+ ```bash
265
+ npm install
266
+ npm run typecheck
267
+ npm run build
268
+ npm pack --dry-run
269
+ ```
270
+
271
+ Before publishing, verify the package contents and test installation from the generated tarball.
272
+
273
+ ## License
274
+
275
+ MIT. See [LICENSE](./LICENSE).
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Apexa — configurable, strongly typed HTTP client.
3
+ *
4
+ * @packageDocumentation
5
+ */
6
+ import type { ApiResponse, ApexaConfig, ApexaErrorCode, ApexaErrorOptions, ApexaRequestMethods, HttpAdapter, InternalRequestConfig, InterceptorId, RequestBody, RequestOptions, ResponseInterpreter } from "./types.js";
7
+ /**
8
+ * Standardized error thrown by Apexa.
9
+ *
10
+ * Use `code` for programmatic handling and `response` to inspect an HTTP
11
+ * response when one was received.
12
+ */
13
+ export declare class ApexaError extends Error {
14
+ /** Stable error code. */
15
+ readonly code: ApexaErrorCode;
16
+ /** Request configuration, when available. */
17
+ readonly config?: InternalRequestConfig;
18
+ /** Parsed response, when available. */
19
+ readonly response?: ApiResponse<unknown>;
20
+ /**
21
+ * Create an Apexa error.
22
+ *
23
+ * @param message - Human-readable error message.
24
+ * @param options - Error code and optional diagnostic context.
25
+ */
26
+ constructor(message: string, options: ApexaErrorOptions);
27
+ }
28
+ /** Alias for applications that prefer the name `ApiError`. */
29
+ export { ApexaError as ApiError };
30
+ interface InterceptorHandler<F, R> {
31
+ readonly id: InterceptorId;
32
+ readonly fulfilled?: F;
33
+ readonly rejected?: R;
34
+ }
35
+ /**
36
+ * Manages registration, removal, and snapshotting of interceptors.
37
+ *
38
+ * Interceptor identifiers remain stable until removed. Removing an interceptor
39
+ * does not alter requests that have already taken their snapshot.
40
+ */
41
+ declare class InterceptorManager<F, R> {
42
+ private handlers;
43
+ private nextId;
44
+ /**
45
+ * Register a fulfilled and/or rejected callback.
46
+ *
47
+ * @returns An identifier for later removal with `eject`.
48
+ */
49
+ use(fulfilled?: F, rejected?: R): InterceptorId;
50
+ /** Remove a registered interceptor. Unknown IDs are ignored. */
51
+ eject(id: InterceptorId): void;
52
+ /** Remove all interceptors from this manager. */
53
+ clear(): void;
54
+ /** Return a stable snapshot of the current handlers. */
55
+ snapshot(): ReadonlyArray<InterceptorHandler<F, R>>;
56
+ }
57
+ /**
58
+ * Public request and response interceptor registry.
59
+ *
60
+ * Request interceptors execute in reverse registration order.
61
+ * Response interceptors execute in registration order.
62
+ */
63
+ export declare class InterceptorRegistry {
64
+ /** Request interceptors. */
65
+ readonly request: InterceptorManager<(config: InternalRequestConfig) => InternalRequestConfig | Promise<InternalRequestConfig>, (error: unknown) => unknown>;
66
+ /** Response interceptors. */
67
+ readonly response: InterceptorManager<(response: ApiResponse<unknown>) => ApiResponse<unknown> | Promise<ApiResponse<unknown>>, (error: unknown) => unknown>;
68
+ }
69
+ /**
70
+ * Default response interpreter.
71
+ *
72
+ * JSON content types are parsed as JSON. Other content types are returned
73
+ * as text. Empty and bodyless responses return `undefined`.
74
+ */
75
+ export declare const defaultInterpreter: ResponseInterpreter;
76
+ /**
77
+ * Default Fetch-based transport adapter.
78
+ *
79
+ * It sends the normalized request configuration and returns the native
80
+ * `Response`. Response parsing and HTTP status handling are performed by Apexa.
81
+ */
82
+ export declare const fetchAdapter: HttpAdapter;
83
+ /**
84
+ * Configurable HTTP client with typed response methods and interceptors.
85
+ *
86
+ * Instance defaults can be overridden on each request, including `baseUrl`
87
+ * and `basePath`.
88
+ *
89
+ * @example
90
+ * ```ts
91
+ * const api = new Apexa({
92
+ * baseUrl: "https://api.example.com",
93
+ * basePath: "/api/v1",
94
+ * timeout: 10_000,
95
+ * });
96
+ *
97
+ * const response = await api.get<User>("/users/123");
98
+ * console.log(response.data);
99
+ *
100
+ * // Override both URL settings for one request.
101
+ * const other = await api.get<User>("/users/123", {
102
+ * baseUrl: "https://other.example.com",
103
+ * basePath: "/v2",
104
+ * });
105
+ * ```
106
+ */
107
+ export declare class Apexa implements ApexaRequestMethods {
108
+ /** Request and response interceptors. */
109
+ readonly interceptors: InterceptorRegistry;
110
+ private readonly defaults;
111
+ /**
112
+ * Create an Apexa instance.
113
+ *
114
+ * @param config - Default options used by requests.
115
+ */
116
+ constructor(config?: ApexaConfig);
117
+ /**
118
+ * Execute a request using the configured request pipeline.
119
+ *
120
+ * @typeParam T - Expected response data type.
121
+ * @param url - Absolute URL or relative endpoint path.
122
+ * @param options - Per-request overrides.
123
+ * @returns Parsed response and request metadata.
124
+ */
125
+ request<T = unknown>(url: string, options?: RequestOptions): Promise<ApiResponse<T>>;
126
+ /** Execute a GET request. */
127
+ get<T = unknown>(url: string, options?: Omit<RequestOptions, "method" | "body">): Promise<ApiResponse<T>>;
128
+ /** Execute a DELETE request. */
129
+ delete<T = unknown>(url: string, options?: Omit<RequestOptions, "method" | "body">): Promise<ApiResponse<T>>;
130
+ /** Execute a HEAD request. */
131
+ head(url: string, options?: Omit<RequestOptions, "method" | "body">): Promise<ApiResponse<undefined>>;
132
+ /** Execute an OPTIONS request. */
133
+ options<T = unknown>(url: string, options?: Omit<RequestOptions, "method" | "body">): Promise<ApiResponse<T>>;
134
+ /** Execute a POST request. */
135
+ post<T = unknown>(url: string, body?: RequestBody, options?: Omit<RequestOptions, "method" | "body">): Promise<ApiResponse<T>>;
136
+ /** Execute a PUT request. */
137
+ put<T = unknown>(url: string, body?: RequestBody, options?: Omit<RequestOptions, "method" | "body">): Promise<ApiResponse<T>>;
138
+ /** Execute a PATCH request. */
139
+ patch<T = unknown>(url: string, body?: RequestBody, options?: Omit<RequestOptions, "method" | "body">): Promise<ApiResponse<T>>;
140
+ private applyCsrf;
141
+ private performWithRetry;
142
+ private runResponseFulfillmentChain;
143
+ private runResponseRejectionChain;
144
+ }
145
+ /** Default export for convenient imports. */
146
+ export default Apexa;
147
+ /** Re-export the public types from the package entry point. */
148
+ export type { ApiResponse, ApexaConfig, ApexaErrorCode, ApexaErrorOptions, ApexaRequestMethods, ClientOptions, CsrfOptions, CredentialsMode, FetchOptions, HttpAdapter, HttpMethod, InternalRequestConfig, InterceptorId, QueryParams, QueryScalar, QueryValue, RequestBody, RequestMetadata, RequestOptions, ResponseInterpreter, RetryOptions, RetryStatus, } from "./types.js";
149
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}