create-request 1.6.0 → 2.0.0-next.0

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.
@@ -1,101 +0,0 @@
1
- import { BaseRequest } from "./BaseRequest.js";
2
- import type { Body, GraphQLOptions } from "./types.js";
3
- import type { ResponseWrapper } from "./ResponseWrapper.js";
4
- /**
5
- * Base class for requests that can have a body (POST, PUT, PATCH)
6
- */
7
- export declare abstract class BodyRequest extends BaseRequest {
8
- protected body?: Body;
9
- private bodyType?;
10
- private graphQLOptions;
11
- constructor(url: string);
12
- /**
13
- * Sets the request body. Automatically detects the body type and sets appropriate Content-Type header.
14
- * Supports JSON objects/arrays, strings, FormData, Blob, ArrayBuffer, URLSearchParams, and ReadableStream.
15
- *
16
- * @param body - The request body. Can be:
17
- * - A JSON-serializable object or array (automatically stringified)
18
- * - A string (sets Content-Type to `text/plain` if not already set)
19
- * - FormData, Blob, File, ArrayBuffer, TypedArray, URLSearchParams, or ReadableStream
20
- * @returns The request instance for chaining
21
- * @throws {RequestError} If the body is a JSON object that cannot be stringified
22
- *
23
- * @example
24
- * ```typescript
25
- * // JSON object (automatically stringified)
26
- * request.withBody({ name: 'John', age: 30 });
27
- *
28
- * @example
29
- * // JSON array
30
- * request.withBody([1, 2, 3]);
31
- *
32
- * @example
33
- * // String
34
- * request.withBody('plain text');
35
- *
36
- * @example
37
- * // FormData
38
- * const formData = new FormData();
39
- * formData.append('file', fileBlob);
40
- * request.withBody(formData);
41
- *
42
- * @example
43
- * // Blob
44
- * request.withBody(new Blob(['content'], { type: 'text/plain' }));
45
- * ```
46
- */
47
- withBody(body: Body): this;
48
- /**
49
- * Sets a GraphQL query or mutation as the request body.
50
- * Automatically formats the body as JSON and sets Content-Type to `application/json`.
51
- * If `throwOnError` is enabled in options, the response will be checked for GraphQL errors
52
- * and a RequestError will be thrown if any are found.
53
- *
54
- * @param query - The GraphQL query or mutation string (e.g., `'query { user { id } }'`)
55
- * @param variables - Optional variables object to pass with the query. Must be a plain object.
56
- * @param options - Optional GraphQL-specific options
57
- * @param options.throwOnError - If `true`, throws a RequestError when the GraphQL response contains errors
58
- * @returns The request instance for chaining
59
- * @throws {RequestError} If the query is empty, variables is invalid, or JSON stringification fails
60
- *
61
- * @example
62
- * ```typescript
63
- * // Simple query with variables
64
- * const request = create.post('/graphql')
65
- * .withGraphQL('query { user(id: $id) { name email } }', { id: '123' });
66
- * const data = await request.getJson();
67
- * ```
68
- *
69
- * @example
70
- * ```typescript
71
- * // Mutation with variables
72
- * const request = create.post('/graphql')
73
- * .withGraphQL('mutation { createUser(name: $name) { id } }', { name: 'John' });
74
- * ```
75
- *
76
- * @example
77
- * ```typescript
78
- * // Throw error if GraphQL response contains errors
79
- * const request = create.post('/graphql')
80
- * .withGraphQL('query { user { id } }', undefined, { throwOnError: true });
81
- * // If the response has errors, this will throw a RequestError
82
- * const data = await request.getJson();
83
- * ```
84
- */
85
- withGraphQL(query: string, variables?: Record<string, unknown>, options?: GraphQLOptions): this;
86
- /**
87
- * Check if Content-Type header is already set (case-insensitive)
88
- */
89
- private hasContentType;
90
- private setContentTypeIfNeeded;
91
- /**
92
- * Get the GraphQL options if set
93
- * @returns The GraphQL options or undefined
94
- */
95
- protected getGraphQLOptions(): GraphQLOptions | undefined;
96
- /**
97
- * Execute the request and return the ResponseWrapper
98
- * Overrides the base implementation to add body handling
99
- */
100
- getResponse(): Promise<ResponseWrapper>;
101
- }
@@ -1,171 +0,0 @@
1
- /**
2
- * Error class for HTTP request failures.
3
- * Extends the standard Error class with additional context about the failed request.
4
- *
5
- * @example
6
- * ```typescript
7
- * try {
8
- * await create.get('/api/users').getJson();
9
- * } catch (error) {
10
- * console.log(`Request failed: ${error.message}`);
11
- * console.log(`URL: ${error.url}`);
12
- * console.log(`Method: ${error.method}`);
13
- * console.log(`Status: ${error.status}`);
14
- * console.log(`Body: ${error.body}`); // Raw response body (if available)
15
- * console.log(error.getJson()); // Body parsed as JSON (or undefined)
16
- * console.log(`Is timeout: ${error.isTimeout}`);
17
- * console.log(`Is aborted: ${error.isAborted}`);
18
- * }
19
- * ```
20
- */
21
- export declare class RequestError extends Error {
22
- /** HTTP status code if the request received a response (e.g., 404, 500) */
23
- readonly status?: number;
24
- /** The Response object if the request received a response before failing */
25
- readonly response?: Response;
26
- /**
27
- * The raw response body as text, if a response was received and its body could be read.
28
- * `undefined` for errors without a response (network errors, timeouts, aborts)
29
- * or when the body could not be read.
30
- */
31
- readonly body?: string;
32
- /** The URL that was requested */
33
- readonly url: string;
34
- /** The HTTP method that was used (e.g., 'GET', 'POST') */
35
- readonly method: string;
36
- /** Whether the request failed due to a timeout */
37
- readonly isTimeout: boolean;
38
- /** Whether the request was aborted (cancelled) */
39
- readonly isAborted: boolean;
40
- /** Cached result of parsing `body` as JSON (lazily populated by getJson) */
41
- private parsedBody?;
42
- /**
43
- * Creates a new RequestError instance.
44
- *
45
- * @param message - Error message describing what went wrong
46
- * @param url - The URL that was requested
47
- * @param method - The HTTP method that was used
48
- * @param options - Additional error context
49
- * @param options.status - HTTP status code if available
50
- * @param options.response - The Response object if available
51
- * @param options.body - The raw response body as text, if available
52
- * @param options.isTimeout - Whether this was a timeout error
53
- * @param options.isAborted - Whether the request was aborted
54
- * @param options.cause - The underlying error that caused this error
55
- */
56
- constructor(message: string, url: string, method: string, options?: {
57
- status?: number;
58
- response?: Response;
59
- body?: string;
60
- isTimeout?: boolean;
61
- isAborted?: boolean;
62
- cause?: Error;
63
- });
64
- /**
65
- * Parses the captured response body (`body`) as JSON.
66
- * The result is cached, so repeated calls don't re-parse.
67
- * This method never throws - it returns `undefined` when there is no body
68
- * or the body is not valid JSON, making it safe to use in error handlers.
69
- *
70
- * @returns The parsed JSON body, or `undefined` if no body was captured or it isn't valid JSON
71
- *
72
- * @example
73
- * ```typescript
74
- * try {
75
- * await create.post('/api/users').withBody(user).getJson();
76
- * } catch (error) {
77
- * if (error instanceof RequestError) {
78
- * const details = error.getJson<{ message: string; code: string }>();
79
- * console.log(details?.message ?? error.body ?? error.message);
80
- * }
81
- * }
82
- * ```
83
- */
84
- getJson<T = unknown>(): T | undefined;
85
- /**
86
- * Safely reads the body of a Response as text without consuming it.
87
- * The response is cloned before reading, so the original body remains readable.
88
- * Never throws - returns `undefined` if the body is unavailable or cannot be read
89
- * (e.g., already consumed, locked stream, or read failure).
90
- *
91
- * @param response - The Response to read the body from
92
- * @returns The body as text, or `undefined` if it could not be read
93
- *
94
- * @example
95
- * ```typescript
96
- * const body = await RequestError.captureBody(response);
97
- * throw RequestError.fromResponse(response, url, 'GET', body);
98
- * ```
99
- */
100
- static captureBody(response: Response): Promise<string | undefined>;
101
- /**
102
- * Creates a RequestError for a timeout failure.
103
- *
104
- * @param url - The URL that timed out
105
- * @param method - The HTTP method that was used
106
- * @param timeoutMs - The timeout duration in milliseconds
107
- * @returns A RequestError with `isTimeout` set to `true`
108
- *
109
- * @example
110
- * ```typescript
111
- * throw RequestError.timeout('/api/data', 'GET', 5000);
112
- * ```
113
- */
114
- static timeout(url: string, method: string, timeoutMs: number): RequestError;
115
- /**
116
- * Creates a RequestError from an HTTP error response.
117
- * Used when the server returns a non-2xx status code.
118
- *
119
- * @param response - The Response object from the failed request
120
- * @param url - The URL that was requested
121
- * @param method - The HTTP method that was used
122
- * @param body - The response body as text, if already read (see {@link RequestError.captureBody})
123
- * @returns A RequestError with the status code, response object, and body (if provided)
124
- *
125
- * @example
126
- * ```typescript
127
- * const response = await fetch('/api/users');
128
- * if (!response.ok) {
129
- * const body = await RequestError.captureBody(response);
130
- * throw RequestError.fromResponse(response, '/api/users', 'GET', body);
131
- * }
132
- * ```
133
- */
134
- static fromResponse(response: Response, url: string, method: string, body?: string): RequestError;
135
- /**
136
- * Creates a RequestError from a network-level error.
137
- * Automatically detects and categorizes common network errors (timeouts, DNS errors, connection errors).
138
- *
139
- * @param url - The URL that failed
140
- * @param method - The HTTP method that was used
141
- * @param originalError - The original error that occurred (e.g., from fetch)
142
- * @returns A RequestError with enhanced error message and context
143
- *
144
- * @example
145
- * ```typescript
146
- * try {
147
- * await fetch('/api/data');
148
- * } catch (error) {
149
- * if (error instanceof Error) {
150
- * throw RequestError.networkError('/api/data', 'GET', error);
151
- * }
152
- * }
153
- * ```
154
- */
155
- static networkError(url: string, method: string, originalError: Error): RequestError;
156
- /**
157
- * Creates a RequestError for an aborted (cancelled) request.
158
- *
159
- * @param url - The URL that was aborted
160
- * @param method - The HTTP method that was used
161
- * @returns A RequestError with `isAborted` set to `true`
162
- *
163
- * @example
164
- * ```typescript
165
- * const controller = new AbortController();
166
- * controller.abort();
167
- * throw RequestError.abortError('/api/data', 'GET');
168
- * ```
169
- */
170
- static abortError(url: string, method: string): RequestError;
171
- }
@@ -1,182 +0,0 @@
1
- import type { GraphQLOptions } from "./types.js";
2
- /**
3
- * Wrapper for HTTP responses with methods to transform the response data.
4
- * Provides convenient methods to parse the response body in different formats.
5
- * Response bodies are cached after the first read, so you can call multiple methods
6
- * (e.g., `getJson()` and `getText()`) on the same response.
7
- *
8
- * @example
9
- * ```typescript
10
- * const response = await create.get('/api/users').getResponse();
11
- * console.log(response.status); // 200
12
- * console.log(response.ok); // true
13
- * const data = await response.getJson();
14
- * ```
15
- */
16
- export declare class ResponseWrapper {
17
- /** The URL that was requested (if available) */
18
- readonly url?: string;
19
- /** The HTTP method that was used (if available) */
20
- readonly method?: string;
21
- private readonly response;
22
- private graphQLOptions?;
23
- private cachedBlob?;
24
- private cachedText?;
25
- private cachedJson?;
26
- private cachedArrayBuffer?;
27
- constructor(response: Response, url?: string, method?: string, graphQLOptions?: GraphQLOptions);
28
- /**
29
- * HTTP status code (e.g., 200, 404, 500)
30
- */
31
- get status(): number;
32
- /**
33
- * HTTP status text (e.g., "OK", "Not Found", "Internal Server Error")
34
- */
35
- get statusText(): string;
36
- /**
37
- * Response headers as a Headers object
38
- */
39
- get headers(): Headers;
40
- /**
41
- * Whether the response status is in the 200-299 range (successful)
42
- */
43
- get ok(): boolean;
44
- /**
45
- * The raw Response object from the fetch API.
46
- * Use this if you need direct access to the underlying Response.
47
- */
48
- get raw(): Response;
49
- /**
50
- * Check if the response body has already been consumed and throw an error if so
51
- * @throws RequestError if the body has already been consumed
52
- */
53
- private checkBodyNotConsumed;
54
- /**
55
- * Check for GraphQL errors and throw if throwOnError is enabled
56
- * @param data - The parsed JSON data
57
- * @throws RequestError if GraphQL response contains errors and throwOnError is enabled
58
- */
59
- private checkGraphQLErrors;
60
- /**
61
- * Parse the response body as JSON
62
- * If GraphQL options are set with throwOnError=true, will check for GraphQL errors and throw.
63
- *
64
- * Returns `null` for empty responses (204 No Content, content-length: 0, or empty body).
65
- * This handles common API patterns where PUT/DELETE operations return no content on success.
66
- *
67
- * @returns The parsed JSON data, or `null` for empty responses
68
- * @throws {RequestError} When the request fails, JSON parsing fails, or GraphQL errors occur (if throwOnError enabled).
69
- *
70
- * @example
71
- * const data = await response.getJson();
72
- * if (data !== null) {
73
- * console.log(data.items);
74
- * }
75
- *
76
- * @example
77
- * // Error handling - errors are always RequestError
78
- * try {
79
- * const data = await response.getJson();
80
- * } catch (error) {
81
- * if (error instanceof RequestError) {
82
- * console.log(error.status, error.url, error.method);
83
- * }
84
- * }
85
- */
86
- getJson<T = unknown>(): Promise<T | null>;
87
- /**
88
- * Get the response body as text.
89
- * The result is cached, so subsequent calls return the same value without re-reading the body.
90
- *
91
- * @returns A promise that resolves to the response body as a string
92
- * @throws {RequestError} When the body has already been consumed or reading fails
93
- *
94
- * @example
95
- * ```typescript
96
- * const text = await response.getText();
97
- * console.log(text); // "Hello, world!"
98
- * ```
99
- */
100
- getText(): Promise<string>;
101
- /**
102
- * Get the response body as a Blob.
103
- * Useful for downloading files or handling binary data.
104
- * The result is cached, so subsequent calls return the same value without re-reading the body.
105
- *
106
- * @returns A promise that resolves to the response body as a Blob
107
- * @throws {RequestError} When the body has already been consumed or reading fails
108
- *
109
- * @example
110
- * ```typescript
111
- * const blob = await response.getBlob();
112
- * const url = URL.createObjectURL(blob);
113
- * // Use the blob URL for downloading or displaying
114
- * ```
115
- */
116
- getBlob(): Promise<Blob>;
117
- /**
118
- * Get the response body as an ArrayBuffer.
119
- * Useful for processing binary data at a low level.
120
- * The result is cached, so subsequent calls return the same value without re-reading the body.
121
- *
122
- * @returns A promise that resolves to the response body as an ArrayBuffer
123
- * @throws {RequestError} When the body has already been consumed or reading fails
124
- *
125
- * @example
126
- * ```typescript
127
- * const buffer = await response.getArrayBuffer();
128
- * const uint8Array = new Uint8Array(buffer);
129
- * // Process the binary data
130
- * ```
131
- */
132
- getArrayBuffer(): Promise<ArrayBuffer>;
133
- /**
134
- * Get the raw response body as a ReadableStream
135
- * Note: This consumes the response body and should only be called once.
136
- * Unlike other methods, streams cannot be cached, so this will throw if the body is already consumed.
137
- *
138
- * @returns The response body as a ReadableStream or null
139
- * @throws {RequestError} When the response body has already been consumed
140
- *
141
- * @example
142
- * const stream = response.getBody();
143
- * if (stream) {
144
- * const reader = stream.getReader();
145
- * // Process the stream
146
- * }
147
- */
148
- getBody(): ReadableStream<Uint8Array> | null;
149
- /**
150
- * Extract specific data using a selector function
151
- * If no selector is provided, returns the full JSON response.
152
- *
153
- * Returns `null` for empty responses (204 No Content, content-length: 0, or empty body).
154
- * If a selector is provided and data is `null`, the selector will receive `null`.
155
- *
156
- * @param selector - Optional function to extract and transform data
157
- * @returns A promise that resolves to the selected data, or `null` for empty responses
158
- * @throws {RequestError} When the request fails, JSON parsing fails, or the selector throws an error
159
- *
160
- * @example
161
- * // Get full response
162
- * const data = await response.getData();
163
- * if (data !== null) {
164
- * console.log(data.items);
165
- * }
166
- *
167
- * @example
168
- * // Extract specific data (use null-safe selector for empty responses)
169
- * const users = await response.getData(data => data?.results?.users);
170
- *
171
- * @example
172
- * // Error handling - errors are always RequestError
173
- * try {
174
- * const data = await response.getData();
175
- * } catch (error) {
176
- * if (error instanceof RequestError) {
177
- * console.log(error.status, error.url, error.method);
178
- * }
179
- * }
180
- */
181
- getData<T = unknown, R = T>(selector?: (data: T | null) => R): Promise<T | R | null>;
182
- }