@marianmeres/http-utils 2.4.0 → 2.5.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/dist/api.d.ts +4 -4
- package/dist/api.js +50 -25
- package/package.json +1 -1
package/dist/api.d.ts
CHANGED
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
* Request body data type.
|
|
9
9
|
* Supports JSON-serializable objects, FormData for file uploads, or raw strings.
|
|
10
10
|
*/
|
|
11
|
-
export type RequestData =
|
|
11
|
+
export type RequestData = object | FormData | string | null;
|
|
12
12
|
interface BaseParams {
|
|
13
|
-
method:
|
|
13
|
+
method: "GET" | "POST" | "PATCH" | "DELETE" | "PUT";
|
|
14
14
|
path: string;
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
@@ -22,11 +22,11 @@ export interface FetchParams {
|
|
|
22
22
|
/** Bearer token (auto-adds `Authorization: Bearer {token}` header). */
|
|
23
23
|
token?: string | null;
|
|
24
24
|
/** Custom request headers. */
|
|
25
|
-
headers?: Record<string, string> | null;
|
|
25
|
+
headers?: HeadersInit | Record<string, string> | null;
|
|
26
26
|
/** AbortSignal for request cancellation. */
|
|
27
27
|
signal?: AbortSignal;
|
|
28
28
|
/** Credentials mode for the request. */
|
|
29
|
-
credentials?:
|
|
29
|
+
credentials?: "omit" | "same-origin" | "include" | null;
|
|
30
30
|
/** If true, returns the raw Response object instead of parsed body. */
|
|
31
31
|
raw?: boolean | null;
|
|
32
32
|
/** If false, does not throw on HTTP errors (default: true). */
|
package/dist/api.js
CHANGED
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
* HTTP API client factory and related types.
|
|
5
5
|
* Provides a convenient wrapper over the native `fetch` API with sensible defaults.
|
|
6
6
|
*/
|
|
7
|
-
import { createHttpError } from
|
|
7
|
+
import { createHttpError } from "./error.js";
|
|
8
8
|
/**
|
|
9
9
|
* Deep merges two objects. Later properties overwrite earlier properties.
|
|
10
10
|
*/
|
|
11
11
|
function deepMerge(target, source) {
|
|
12
12
|
const output = { ...target };
|
|
13
13
|
if (isObject(target) && isObject(source)) {
|
|
14
|
-
Object.keys(source).forEach(key => {
|
|
14
|
+
Object.keys(source).forEach((key) => {
|
|
15
15
|
const sourceVal = source[key];
|
|
16
16
|
const targetVal = target[key];
|
|
17
17
|
if (isObject(sourceVal)) {
|
|
@@ -30,10 +30,10 @@ function deepMerge(target, source) {
|
|
|
30
30
|
return output;
|
|
31
31
|
}
|
|
32
32
|
function isObject(item) {
|
|
33
|
-
return item !== null && typeof item ===
|
|
33
|
+
return item !== null && typeof item === "object" && !Array.isArray(item);
|
|
34
34
|
}
|
|
35
35
|
/** Symbol marker for explicit options API detection. */
|
|
36
|
-
const OPTIONS_MARKER = Symbol(
|
|
36
|
+
const OPTIONS_MARKER = Symbol("options");
|
|
37
37
|
/**
|
|
38
38
|
* Marks an options object for the new options API.
|
|
39
39
|
* Use this to explicitly indicate you're using the options-based API.
|
|
@@ -75,7 +75,7 @@ function parseGetOptions(paramsOrOptions, legacyRespHeaders, legacyErrorExtracto
|
|
|
75
75
|
*/
|
|
76
76
|
function parseDataOptions(dataOrOptions, legacyParams, legacyRespHeaders, legacyErrorExtractor) {
|
|
77
77
|
if (dataOrOptions &&
|
|
78
|
-
typeof dataOrOptions ===
|
|
78
|
+
typeof dataOrOptions === "object" &&
|
|
79
79
|
OPTIONS_MARKER in dataOrOptions) {
|
|
80
80
|
// New options API (explicit via opts() wrapper)
|
|
81
81
|
const o = dataOrOptions;
|
|
@@ -95,15 +95,20 @@ function parseDataOptions(dataOrOptions, legacyParams, legacyRespHeaders, legacy
|
|
|
95
95
|
};
|
|
96
96
|
}
|
|
97
97
|
const _fetchRaw = async ({ method, path, data = null, token = null, headers = null, signal, credentials, }) => {
|
|
98
|
-
const normalizedHeaders =
|
|
98
|
+
const normalizedHeaders = {};
|
|
99
|
+
if (headers) {
|
|
100
|
+
new Headers(headers).forEach((value, key) => {
|
|
101
|
+
normalizedHeaders[key] = value;
|
|
102
|
+
});
|
|
103
|
+
}
|
|
99
104
|
const opts = {
|
|
100
105
|
method,
|
|
101
106
|
credentials: credentials ?? undefined,
|
|
102
107
|
headers: normalizedHeaders,
|
|
103
|
-
signal
|
|
108
|
+
signal,
|
|
104
109
|
};
|
|
105
110
|
if (data) {
|
|
106
|
-
const isObj = typeof data ===
|
|
111
|
+
const isObj = typeof data === "object";
|
|
107
112
|
// FormData: multipart/form-data -- no explicit Content-Type
|
|
108
113
|
if (data instanceof FormData) {
|
|
109
114
|
opts.body = data;
|
|
@@ -111,15 +116,15 @@ const _fetchRaw = async ({ method, path, data = null, token = null, headers = nu
|
|
|
111
116
|
// Cover 99% of use cases (may not fit all scenarios)
|
|
112
117
|
else {
|
|
113
118
|
// If not explicitly stated, assume JSON
|
|
114
|
-
if (isObj || !normalizedHeaders[
|
|
115
|
-
normalizedHeaders[
|
|
119
|
+
if (isObj || !normalizedHeaders["content-type"]) {
|
|
120
|
+
normalizedHeaders["content-type"] = "application/json";
|
|
116
121
|
}
|
|
117
122
|
opts.body = JSON.stringify(data);
|
|
118
123
|
}
|
|
119
124
|
}
|
|
120
125
|
// Opinionated convention: auto-add Bearer token
|
|
121
126
|
if (token) {
|
|
122
|
-
normalizedHeaders[
|
|
127
|
+
normalizedHeaders["authorization"] = `Bearer ${token}`;
|
|
123
128
|
}
|
|
124
129
|
opts.headers = normalizedHeaders;
|
|
125
130
|
return await fetch(path, opts);
|
|
@@ -159,7 +164,7 @@ const _fetch = async (params, respHeaders = null, errorMessageExtractor = null,
|
|
|
159
164
|
b?.message ||
|
|
160
165
|
b?.error ||
|
|
161
166
|
_response?.statusText ||
|
|
162
|
-
|
|
167
|
+
"Unknown error");
|
|
163
168
|
if (msg.length > 255)
|
|
164
169
|
msg = `[Shortened]: ${msg.slice(0, 255)}`;
|
|
165
170
|
return msg;
|
|
@@ -200,40 +205,60 @@ export class HttpApi {
|
|
|
200
205
|
return deepMerge(a, b);
|
|
201
206
|
}
|
|
202
207
|
async #getDefs() {
|
|
203
|
-
if (typeof this.#defaults ===
|
|
208
|
+
if (typeof this.#defaults === "function") {
|
|
204
209
|
return { ...(await this.#defaults()) };
|
|
205
210
|
}
|
|
206
211
|
return { ...(this.#defaults || {}) };
|
|
207
212
|
}
|
|
208
213
|
#buildPath(path, base) {
|
|
209
|
-
base = `${base ||
|
|
210
|
-
path = `${path ||
|
|
214
|
+
base = `${base || ""}`;
|
|
215
|
+
path = `${path || ""}`;
|
|
211
216
|
return /^https?:/.test(path) ? path : base + path;
|
|
212
217
|
}
|
|
213
218
|
async get(path, paramsOrOptions, respHeaders, errorMessageExtractor, _dumpParams = false) {
|
|
214
|
-
const { params, respHeaders: headers, errorExtractor } = parseGetOptions(paramsOrOptions, respHeaders, errorMessageExtractor);
|
|
219
|
+
const { params, respHeaders: headers, errorExtractor, } = parseGetOptions(paramsOrOptions, respHeaders, errorMessageExtractor);
|
|
215
220
|
path = this.#buildPath(path, this.#base);
|
|
216
|
-
return _fetch(this.#merge(await this.#getDefs(), { ...params, method:
|
|
221
|
+
return _fetch(this.#merge(await this.#getDefs(), { ...params, method: "GET", path }), headers, errorExtractor ?? this.#factoryErrorMessageExtractor, _dumpParams);
|
|
217
222
|
}
|
|
218
223
|
async post(path, dataOrOptions, params, respHeaders, errorMessageExtractor, _dumpParams = false) {
|
|
219
|
-
const { data, params: fetchParams, respHeaders: headers, errorExtractor } = parseDataOptions(dataOrOptions, params, respHeaders, errorMessageExtractor);
|
|
224
|
+
const { data, params: fetchParams, respHeaders: headers, errorExtractor, } = parseDataOptions(dataOrOptions, params, respHeaders, errorMessageExtractor);
|
|
220
225
|
path = this.#buildPath(path, this.#base);
|
|
221
|
-
return _fetch(this.#merge(await this.#getDefs(), {
|
|
226
|
+
return _fetch(this.#merge(await this.#getDefs(), {
|
|
227
|
+
...(fetchParams || {}),
|
|
228
|
+
data,
|
|
229
|
+
method: "POST",
|
|
230
|
+
path,
|
|
231
|
+
}), headers, errorExtractor ?? this.#factoryErrorMessageExtractor, _dumpParams);
|
|
222
232
|
}
|
|
223
233
|
async put(path, dataOrOptions, params, respHeaders, errorMessageExtractor, _dumpParams = false) {
|
|
224
|
-
const { data, params: fetchParams, respHeaders: headers, errorExtractor } = parseDataOptions(dataOrOptions, params, respHeaders, errorMessageExtractor);
|
|
234
|
+
const { data, params: fetchParams, respHeaders: headers, errorExtractor, } = parseDataOptions(dataOrOptions, params, respHeaders, errorMessageExtractor);
|
|
225
235
|
path = this.#buildPath(path, this.#base);
|
|
226
|
-
return _fetch(this.#merge(await this.#getDefs(), {
|
|
236
|
+
return _fetch(this.#merge(await this.#getDefs(), {
|
|
237
|
+
...(fetchParams || {}),
|
|
238
|
+
data,
|
|
239
|
+
method: "PUT",
|
|
240
|
+
path,
|
|
241
|
+
}), headers, errorExtractor ?? this.#factoryErrorMessageExtractor, _dumpParams);
|
|
227
242
|
}
|
|
228
243
|
async patch(path, dataOrOptions, params, respHeaders, errorMessageExtractor, _dumpParams = false) {
|
|
229
|
-
const { data, params: fetchParams, respHeaders: headers, errorExtractor } = parseDataOptions(dataOrOptions, params, respHeaders, errorMessageExtractor);
|
|
244
|
+
const { data, params: fetchParams, respHeaders: headers, errorExtractor, } = parseDataOptions(dataOrOptions, params, respHeaders, errorMessageExtractor);
|
|
230
245
|
path = this.#buildPath(path, this.#base);
|
|
231
|
-
return _fetch(this.#merge(await this.#getDefs(), {
|
|
246
|
+
return _fetch(this.#merge(await this.#getDefs(), {
|
|
247
|
+
...(fetchParams || {}),
|
|
248
|
+
data,
|
|
249
|
+
method: "PATCH",
|
|
250
|
+
path,
|
|
251
|
+
}), headers, errorExtractor ?? this.#factoryErrorMessageExtractor, _dumpParams);
|
|
232
252
|
}
|
|
233
253
|
async del(path, dataOrOptions, params, respHeaders, errorMessageExtractor, _dumpParams = false) {
|
|
234
|
-
const { data, params: fetchParams, respHeaders: headers, errorExtractor } = parseDataOptions(dataOrOptions, params, respHeaders, errorMessageExtractor);
|
|
254
|
+
const { data, params: fetchParams, respHeaders: headers, errorExtractor, } = parseDataOptions(dataOrOptions, params, respHeaders, errorMessageExtractor);
|
|
235
255
|
path = this.#buildPath(path, this.#base);
|
|
236
|
-
return _fetch(this.#merge(await this.#getDefs(), {
|
|
256
|
+
return _fetch(this.#merge(await this.#getDefs(), {
|
|
257
|
+
...(fetchParams || {}),
|
|
258
|
+
data,
|
|
259
|
+
method: "DELETE",
|
|
260
|
+
path,
|
|
261
|
+
}), headers, errorExtractor ?? this.#factoryErrorMessageExtractor, _dumpParams);
|
|
237
262
|
}
|
|
238
263
|
/**
|
|
239
264
|
* Helper method to build the full URL from a path.
|