@inshorts/glint-http 1.2.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.
- package/README.md +177 -0
- package/dist/index.cjs +429 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +200 -0
- package/dist/index.d.ts +200 -0
- package/dist/index.js +384 -0
- package/dist/index.js.map +1 -0
- package/package.json +48 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
type UpstreamClientConfig = {
|
|
2
|
+
/** Read on every request, so tests and deployments can swap it lazily. */
|
|
3
|
+
baseUrl: () => string;
|
|
4
|
+
/** Read on every request; a natural place to attach a system token. */
|
|
5
|
+
headers?: () => HeadersInit;
|
|
6
|
+
/**
|
|
7
|
+
* Builds the error thrown for a non-OK response.
|
|
8
|
+
* Defaults to `UpstreamError`. Third arg is a redacted curl (optional).
|
|
9
|
+
*/
|
|
10
|
+
makeError?: (message: string, status: number, curl?: string) => Error;
|
|
11
|
+
/** Default timeout for this client; see `fetchUpstream`. */
|
|
12
|
+
timeoutMs?: number;
|
|
13
|
+
};
|
|
14
|
+
type UpstreamRequest = Omit<RequestInit, "body" | "headers"> & {
|
|
15
|
+
/** Serialised with `JSON.stringify`. */
|
|
16
|
+
body?: unknown;
|
|
17
|
+
/** Merged over the client's headers; same-named ones win. */
|
|
18
|
+
headers?: HeadersInit;
|
|
19
|
+
/** Overrides the client's timeout for this call. */
|
|
20
|
+
timeoutMs?: number;
|
|
21
|
+
};
|
|
22
|
+
interface UpstreamClient {
|
|
23
|
+
request<T>(path: string, init?: UpstreamRequest): Promise<T>;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Creates a small server-only JSON client. Configuration stays lazy so tests
|
|
27
|
+
* and deployments can substitute environment-backed URLs and credentials.
|
|
28
|
+
*
|
|
29
|
+
* On failure the thrown error has:
|
|
30
|
+
* - `message` — upstream / timeout reason (safe for the API JSON body)
|
|
31
|
+
* - `status` — HTTP status for `errorResponse`
|
|
32
|
+
* - `curl` — redacted replay line for **server logs only**
|
|
33
|
+
*/
|
|
34
|
+
declare function createUpstreamClient(config: UpstreamClientConfig): UpstreamClient;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Turns a request into a `curl` line you can paste into a terminal.
|
|
38
|
+
*
|
|
39
|
+
* The point is the thing that is missing when an upstream call fails in
|
|
40
|
+
* production: the log says a request to some service returned 502, and
|
|
41
|
+
* reproducing it means reading the calling code to work out what was actually
|
|
42
|
+
* sent. This writes that down at the moment it fails.
|
|
43
|
+
*
|
|
44
|
+
* **Nothing secret goes in.** Every header whose name looks like a credential
|
|
45
|
+
* is emitted as `$ENV_VAR` where the value matches a known one, and
|
|
46
|
+
* `<redacted>` otherwise — so the line is still runnable after
|
|
47
|
+
* `export SOME_SYS_TOKEN=…`, without the token itself ever reaching a log
|
|
48
|
+
* aggregator. Body fields that look like credentials get the same treatment.
|
|
49
|
+
*
|
|
50
|
+
* The alternative — logging the real header — is how tokens end up in Cloud
|
|
51
|
+
* Logging, readable by anyone with project viewer, retained for a month, and
|
|
52
|
+
* impossible to rotate out of the archive.
|
|
53
|
+
*/
|
|
54
|
+
interface CurlRequest {
|
|
55
|
+
method?: string;
|
|
56
|
+
url: string;
|
|
57
|
+
headers?: HeadersInit;
|
|
58
|
+
body?: unknown;
|
|
59
|
+
}
|
|
60
|
+
interface CurlOptions {
|
|
61
|
+
/** Longest body to include before truncating. */
|
|
62
|
+
maxBody?: number;
|
|
63
|
+
/**
|
|
64
|
+
* Environment variable names to match secret values against, so the line
|
|
65
|
+
* comes out as `$SOME_SYS_TOKEN` rather than `<redacted>` and can actually
|
|
66
|
+
* be replayed. Defaults to `process.env`; only values of 8+ characters are
|
|
67
|
+
* matched.
|
|
68
|
+
*/
|
|
69
|
+
env?: Record<string, string | undefined>;
|
|
70
|
+
}
|
|
71
|
+
declare function toCurl(request: CurlRequest, options?: CurlOptions): string;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Errors this package throws. Each carries a numeric `status`, so
|
|
75
|
+
* `errorResponse` turns it into the right HTTP code without having to know
|
|
76
|
+
* the class.
|
|
77
|
+
*
|
|
78
|
+
* `curl` is for **server logs only** — never put it in the JSON body sent to
|
|
79
|
+
* the browser (`errorResponse` strips it).
|
|
80
|
+
*/
|
|
81
|
+
/** A required upstream setting (base URL, token) is missing. */
|
|
82
|
+
declare class UpstreamConfigError extends Error {
|
|
83
|
+
status: number;
|
|
84
|
+
curl?: string;
|
|
85
|
+
constructor(message: string, options?: {
|
|
86
|
+
curl?: string;
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
/** The upstream did not answer before the deadline. */
|
|
90
|
+
declare class UpstreamTimeoutError extends Error {
|
|
91
|
+
status: number;
|
|
92
|
+
curl?: string;
|
|
93
|
+
constructor(message?: string, options?: {
|
|
94
|
+
curl?: string;
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* The default error `createUpstreamClient` throws for a non-OK response when
|
|
99
|
+
* the caller does not supply its own `makeError`.
|
|
100
|
+
*/
|
|
101
|
+
declare class UpstreamError extends Error {
|
|
102
|
+
status: number;
|
|
103
|
+
curl?: string;
|
|
104
|
+
constructor(message: string, status: number, options?: {
|
|
105
|
+
curl?: string;
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
/** True when `error` looks like one of ours (or any `{ status, message }`). */
|
|
109
|
+
declare function isUpstreamFailure(error: unknown): error is Error & {
|
|
110
|
+
status: number;
|
|
111
|
+
curl?: string;
|
|
112
|
+
};
|
|
113
|
+
/** Read a redacted replay curl if the thrown value carries one. */
|
|
114
|
+
declare function curlOf(error: unknown): string | undefined;
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Turning a thrown error into an HTTP response, for route handlers.
|
|
118
|
+
*
|
|
119
|
+
* This does not list error classes. Anything thrown with a numeric `status`
|
|
120
|
+
* (every error in this package, and most upstream ones) keeps that status, so
|
|
121
|
+
* an upstream 404 reaches the browser as a 404 rather than a 500.
|
|
122
|
+
*
|
|
123
|
+
* Returns a standard `Response`, which Next.js route handlers, Hono, Remix and
|
|
124
|
+
* any other fetch-style server accept as-is.
|
|
125
|
+
*
|
|
126
|
+
* **Body is always `{ message }` only.** Never include `curl` — that is for
|
|
127
|
+
* Cloud Logging via `logApiError`.
|
|
128
|
+
*/
|
|
129
|
+
/** Only a real HTTP failure code. Anything else is our fault, so 500. */
|
|
130
|
+
declare function statusOf(error: unknown): number;
|
|
131
|
+
declare function messageOf(error: unknown, fallback?: string): string;
|
|
132
|
+
/**
|
|
133
|
+
* `fallback` is used only when the thrown value is not an `Error` (a rejected
|
|
134
|
+
* string, say), or is one with an empty message. A real error's own message is
|
|
135
|
+
* more useful than a generic one.
|
|
136
|
+
*/
|
|
137
|
+
declare function errorResponse(error: unknown, fallback?: string): Response;
|
|
138
|
+
/** A rejected payload: the caller sent something we will not act on. */
|
|
139
|
+
declare function invalidResponse(message: string): Response;
|
|
140
|
+
/**
|
|
141
|
+
* Log an API / upstream failure for Cloud Logging, including redacted curl
|
|
142
|
+
* when present. Call this in a route `catch` **before** `errorResponse`.
|
|
143
|
+
*
|
|
144
|
+
* ```ts
|
|
145
|
+
* } catch (error) {
|
|
146
|
+
* logApiError(error, { service: "inpix-panel", route: "POST /api/x" });
|
|
147
|
+
* return errorResponse(error);
|
|
148
|
+
* }
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
declare function logApiError(error: unknown, context: {
|
|
152
|
+
service: string;
|
|
153
|
+
route?: string;
|
|
154
|
+
requestId?: string;
|
|
155
|
+
}): void;
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Server-side `fetch` for calls to internal upstream services. These calls
|
|
159
|
+
* usually attach system tokens, so never import this into browser code.
|
|
160
|
+
*/
|
|
161
|
+
/**
|
|
162
|
+
* Base headers for an internal service-to-service call. `deviceId` names the
|
|
163
|
+
* calling app (`"inpix-panel"`, `"users-crm"`) so upstream logs show who sent it.
|
|
164
|
+
*/
|
|
165
|
+
declare function internalHeaders(deviceId: string): Record<string, string>;
|
|
166
|
+
/** Used when neither the call nor `UPSTREAM_TIMEOUT_MS` sets a timeout. */
|
|
167
|
+
declare const DEFAULT_UPSTREAM_TIMEOUT_MS = 15000;
|
|
168
|
+
/**
|
|
169
|
+
* Require an absolute upstream base URL. There is deliberately no default
|
|
170
|
+
* host: missing config fails closed instead of quietly calling a hard-coded one.
|
|
171
|
+
*/
|
|
172
|
+
declare function requireUpstreamBaseUrl(value: string | null | undefined, envName: string): string;
|
|
173
|
+
/** Test seam. */
|
|
174
|
+
declare function resetUpstreamFailureLog(): void;
|
|
175
|
+
/**
|
|
176
|
+
* `fetch` with an AbortSignal timeout. Throws `UpstreamTimeoutError` (status
|
|
177
|
+
* 504) when the deadline is hit before the upstream responds.
|
|
178
|
+
*
|
|
179
|
+
* The timeout is `timeoutMs` if given, else the `UPSTREAM_TIMEOUT_MS` env var,
|
|
180
|
+
* else `DEFAULT_UPSTREAM_TIMEOUT_MS`.
|
|
181
|
+
*
|
|
182
|
+
* Every failure — a non-OK status, a timeout, a refused connection — is logged
|
|
183
|
+
* once here with a replayable curl, so no caller has to remember to do it and
|
|
184
|
+
* none of them can do it differently.
|
|
185
|
+
*
|
|
186
|
+
* No caller currently treats a non-OK status as normal flow, so there is no
|
|
187
|
+
* opt-out. If one appears — a lookup where 404 means "absent" — add a
|
|
188
|
+
* `silentStatuses` option here rather than logging around it at the call site.
|
|
189
|
+
*/
|
|
190
|
+
/** Build the redacted replay curl for this attempt (also used on thrown errors). */
|
|
191
|
+
declare function curlForRequest(input: RequestInfo | URL, init?: RequestInit): string;
|
|
192
|
+
declare function fetchUpstream(input: RequestInfo | URL, init?: RequestInit, timeoutMs?: number): Promise<Response>;
|
|
193
|
+
/**
|
|
194
|
+
* Reads an upstream response: returns parsed JSON on success (undefined for
|
|
195
|
+
* 204), otherwise extracts a `message`/`error` field and throws via the
|
|
196
|
+
* provided factory so callers keep their own typed error class + status.
|
|
197
|
+
*/
|
|
198
|
+
declare function parseUpstream<T>(response: Response, makeError: (message: string, status: number) => Error, fallbackMessage?: string): Promise<T>;
|
|
199
|
+
|
|
200
|
+
export { type CurlOptions, type CurlRequest, DEFAULT_UPSTREAM_TIMEOUT_MS, type UpstreamClient, type UpstreamClientConfig, UpstreamConfigError, UpstreamError, type UpstreamRequest, UpstreamTimeoutError, createUpstreamClient, curlForRequest, curlOf, errorResponse, fetchUpstream, internalHeaders, invalidResponse, isUpstreamFailure, logApiError, messageOf, parseUpstream, requireUpstreamBaseUrl, resetUpstreamFailureLog, statusOf, toCurl };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
type UpstreamClientConfig = {
|
|
2
|
+
/** Read on every request, so tests and deployments can swap it lazily. */
|
|
3
|
+
baseUrl: () => string;
|
|
4
|
+
/** Read on every request; a natural place to attach a system token. */
|
|
5
|
+
headers?: () => HeadersInit;
|
|
6
|
+
/**
|
|
7
|
+
* Builds the error thrown for a non-OK response.
|
|
8
|
+
* Defaults to `UpstreamError`. Third arg is a redacted curl (optional).
|
|
9
|
+
*/
|
|
10
|
+
makeError?: (message: string, status: number, curl?: string) => Error;
|
|
11
|
+
/** Default timeout for this client; see `fetchUpstream`. */
|
|
12
|
+
timeoutMs?: number;
|
|
13
|
+
};
|
|
14
|
+
type UpstreamRequest = Omit<RequestInit, "body" | "headers"> & {
|
|
15
|
+
/** Serialised with `JSON.stringify`. */
|
|
16
|
+
body?: unknown;
|
|
17
|
+
/** Merged over the client's headers; same-named ones win. */
|
|
18
|
+
headers?: HeadersInit;
|
|
19
|
+
/** Overrides the client's timeout for this call. */
|
|
20
|
+
timeoutMs?: number;
|
|
21
|
+
};
|
|
22
|
+
interface UpstreamClient {
|
|
23
|
+
request<T>(path: string, init?: UpstreamRequest): Promise<T>;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Creates a small server-only JSON client. Configuration stays lazy so tests
|
|
27
|
+
* and deployments can substitute environment-backed URLs and credentials.
|
|
28
|
+
*
|
|
29
|
+
* On failure the thrown error has:
|
|
30
|
+
* - `message` — upstream / timeout reason (safe for the API JSON body)
|
|
31
|
+
* - `status` — HTTP status for `errorResponse`
|
|
32
|
+
* - `curl` — redacted replay line for **server logs only**
|
|
33
|
+
*/
|
|
34
|
+
declare function createUpstreamClient(config: UpstreamClientConfig): UpstreamClient;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Turns a request into a `curl` line you can paste into a terminal.
|
|
38
|
+
*
|
|
39
|
+
* The point is the thing that is missing when an upstream call fails in
|
|
40
|
+
* production: the log says a request to some service returned 502, and
|
|
41
|
+
* reproducing it means reading the calling code to work out what was actually
|
|
42
|
+
* sent. This writes that down at the moment it fails.
|
|
43
|
+
*
|
|
44
|
+
* **Nothing secret goes in.** Every header whose name looks like a credential
|
|
45
|
+
* is emitted as `$ENV_VAR` where the value matches a known one, and
|
|
46
|
+
* `<redacted>` otherwise — so the line is still runnable after
|
|
47
|
+
* `export SOME_SYS_TOKEN=…`, without the token itself ever reaching a log
|
|
48
|
+
* aggregator. Body fields that look like credentials get the same treatment.
|
|
49
|
+
*
|
|
50
|
+
* The alternative — logging the real header — is how tokens end up in Cloud
|
|
51
|
+
* Logging, readable by anyone with project viewer, retained for a month, and
|
|
52
|
+
* impossible to rotate out of the archive.
|
|
53
|
+
*/
|
|
54
|
+
interface CurlRequest {
|
|
55
|
+
method?: string;
|
|
56
|
+
url: string;
|
|
57
|
+
headers?: HeadersInit;
|
|
58
|
+
body?: unknown;
|
|
59
|
+
}
|
|
60
|
+
interface CurlOptions {
|
|
61
|
+
/** Longest body to include before truncating. */
|
|
62
|
+
maxBody?: number;
|
|
63
|
+
/**
|
|
64
|
+
* Environment variable names to match secret values against, so the line
|
|
65
|
+
* comes out as `$SOME_SYS_TOKEN` rather than `<redacted>` and can actually
|
|
66
|
+
* be replayed. Defaults to `process.env`; only values of 8+ characters are
|
|
67
|
+
* matched.
|
|
68
|
+
*/
|
|
69
|
+
env?: Record<string, string | undefined>;
|
|
70
|
+
}
|
|
71
|
+
declare function toCurl(request: CurlRequest, options?: CurlOptions): string;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Errors this package throws. Each carries a numeric `status`, so
|
|
75
|
+
* `errorResponse` turns it into the right HTTP code without having to know
|
|
76
|
+
* the class.
|
|
77
|
+
*
|
|
78
|
+
* `curl` is for **server logs only** — never put it in the JSON body sent to
|
|
79
|
+
* the browser (`errorResponse` strips it).
|
|
80
|
+
*/
|
|
81
|
+
/** A required upstream setting (base URL, token) is missing. */
|
|
82
|
+
declare class UpstreamConfigError extends Error {
|
|
83
|
+
status: number;
|
|
84
|
+
curl?: string;
|
|
85
|
+
constructor(message: string, options?: {
|
|
86
|
+
curl?: string;
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
/** The upstream did not answer before the deadline. */
|
|
90
|
+
declare class UpstreamTimeoutError extends Error {
|
|
91
|
+
status: number;
|
|
92
|
+
curl?: string;
|
|
93
|
+
constructor(message?: string, options?: {
|
|
94
|
+
curl?: string;
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* The default error `createUpstreamClient` throws for a non-OK response when
|
|
99
|
+
* the caller does not supply its own `makeError`.
|
|
100
|
+
*/
|
|
101
|
+
declare class UpstreamError extends Error {
|
|
102
|
+
status: number;
|
|
103
|
+
curl?: string;
|
|
104
|
+
constructor(message: string, status: number, options?: {
|
|
105
|
+
curl?: string;
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
/** True when `error` looks like one of ours (or any `{ status, message }`). */
|
|
109
|
+
declare function isUpstreamFailure(error: unknown): error is Error & {
|
|
110
|
+
status: number;
|
|
111
|
+
curl?: string;
|
|
112
|
+
};
|
|
113
|
+
/** Read a redacted replay curl if the thrown value carries one. */
|
|
114
|
+
declare function curlOf(error: unknown): string | undefined;
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Turning a thrown error into an HTTP response, for route handlers.
|
|
118
|
+
*
|
|
119
|
+
* This does not list error classes. Anything thrown with a numeric `status`
|
|
120
|
+
* (every error in this package, and most upstream ones) keeps that status, so
|
|
121
|
+
* an upstream 404 reaches the browser as a 404 rather than a 500.
|
|
122
|
+
*
|
|
123
|
+
* Returns a standard `Response`, which Next.js route handlers, Hono, Remix and
|
|
124
|
+
* any other fetch-style server accept as-is.
|
|
125
|
+
*
|
|
126
|
+
* **Body is always `{ message }` only.** Never include `curl` — that is for
|
|
127
|
+
* Cloud Logging via `logApiError`.
|
|
128
|
+
*/
|
|
129
|
+
/** Only a real HTTP failure code. Anything else is our fault, so 500. */
|
|
130
|
+
declare function statusOf(error: unknown): number;
|
|
131
|
+
declare function messageOf(error: unknown, fallback?: string): string;
|
|
132
|
+
/**
|
|
133
|
+
* `fallback` is used only when the thrown value is not an `Error` (a rejected
|
|
134
|
+
* string, say), or is one with an empty message. A real error's own message is
|
|
135
|
+
* more useful than a generic one.
|
|
136
|
+
*/
|
|
137
|
+
declare function errorResponse(error: unknown, fallback?: string): Response;
|
|
138
|
+
/** A rejected payload: the caller sent something we will not act on. */
|
|
139
|
+
declare function invalidResponse(message: string): Response;
|
|
140
|
+
/**
|
|
141
|
+
* Log an API / upstream failure for Cloud Logging, including redacted curl
|
|
142
|
+
* when present. Call this in a route `catch` **before** `errorResponse`.
|
|
143
|
+
*
|
|
144
|
+
* ```ts
|
|
145
|
+
* } catch (error) {
|
|
146
|
+
* logApiError(error, { service: "inpix-panel", route: "POST /api/x" });
|
|
147
|
+
* return errorResponse(error);
|
|
148
|
+
* }
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
declare function logApiError(error: unknown, context: {
|
|
152
|
+
service: string;
|
|
153
|
+
route?: string;
|
|
154
|
+
requestId?: string;
|
|
155
|
+
}): void;
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Server-side `fetch` for calls to internal upstream services. These calls
|
|
159
|
+
* usually attach system tokens, so never import this into browser code.
|
|
160
|
+
*/
|
|
161
|
+
/**
|
|
162
|
+
* Base headers for an internal service-to-service call. `deviceId` names the
|
|
163
|
+
* calling app (`"inpix-panel"`, `"users-crm"`) so upstream logs show who sent it.
|
|
164
|
+
*/
|
|
165
|
+
declare function internalHeaders(deviceId: string): Record<string, string>;
|
|
166
|
+
/** Used when neither the call nor `UPSTREAM_TIMEOUT_MS` sets a timeout. */
|
|
167
|
+
declare const DEFAULT_UPSTREAM_TIMEOUT_MS = 15000;
|
|
168
|
+
/**
|
|
169
|
+
* Require an absolute upstream base URL. There is deliberately no default
|
|
170
|
+
* host: missing config fails closed instead of quietly calling a hard-coded one.
|
|
171
|
+
*/
|
|
172
|
+
declare function requireUpstreamBaseUrl(value: string | null | undefined, envName: string): string;
|
|
173
|
+
/** Test seam. */
|
|
174
|
+
declare function resetUpstreamFailureLog(): void;
|
|
175
|
+
/**
|
|
176
|
+
* `fetch` with an AbortSignal timeout. Throws `UpstreamTimeoutError` (status
|
|
177
|
+
* 504) when the deadline is hit before the upstream responds.
|
|
178
|
+
*
|
|
179
|
+
* The timeout is `timeoutMs` if given, else the `UPSTREAM_TIMEOUT_MS` env var,
|
|
180
|
+
* else `DEFAULT_UPSTREAM_TIMEOUT_MS`.
|
|
181
|
+
*
|
|
182
|
+
* Every failure — a non-OK status, a timeout, a refused connection — is logged
|
|
183
|
+
* once here with a replayable curl, so no caller has to remember to do it and
|
|
184
|
+
* none of them can do it differently.
|
|
185
|
+
*
|
|
186
|
+
* No caller currently treats a non-OK status as normal flow, so there is no
|
|
187
|
+
* opt-out. If one appears — a lookup where 404 means "absent" — add a
|
|
188
|
+
* `silentStatuses` option here rather than logging around it at the call site.
|
|
189
|
+
*/
|
|
190
|
+
/** Build the redacted replay curl for this attempt (also used on thrown errors). */
|
|
191
|
+
declare function curlForRequest(input: RequestInfo | URL, init?: RequestInit): string;
|
|
192
|
+
declare function fetchUpstream(input: RequestInfo | URL, init?: RequestInit, timeoutMs?: number): Promise<Response>;
|
|
193
|
+
/**
|
|
194
|
+
* Reads an upstream response: returns parsed JSON on success (undefined for
|
|
195
|
+
* 204), otherwise extracts a `message`/`error` field and throws via the
|
|
196
|
+
* provided factory so callers keep their own typed error class + status.
|
|
197
|
+
*/
|
|
198
|
+
declare function parseUpstream<T>(response: Response, makeError: (message: string, status: number) => Error, fallbackMessage?: string): Promise<T>;
|
|
199
|
+
|
|
200
|
+
export { type CurlOptions, type CurlRequest, DEFAULT_UPSTREAM_TIMEOUT_MS, type UpstreamClient, type UpstreamClientConfig, UpstreamConfigError, UpstreamError, type UpstreamRequest, UpstreamTimeoutError, createUpstreamClient, curlForRequest, curlOf, errorResponse, fetchUpstream, internalHeaders, invalidResponse, isUpstreamFailure, logApiError, messageOf, parseUpstream, requireUpstreamBaseUrl, resetUpstreamFailureLog, statusOf, toCurl };
|