make-service 0.1.0 → 1.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.
- package/README.md +39 -5
- package/dist/index.d.ts +21 -19
- package/dist/index.js +47 -38
- package/dist/index.mjs +46 -37
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,6 +8,7 @@ It adds a set of little features and allows you to parse responses with [zod](ht
|
|
|
8
8
|
- 🤩 Type-safe return of `response.json()` and `response.text()`. Defaults to `unknown` instead of `any`.
|
|
9
9
|
- 🚦 Easily setup an API with a `baseURL` and common `headers` for every request.
|
|
10
10
|
- 🏗️ Compose URL from the base by just calling the endpoints and an object-like `query`.
|
|
11
|
+
- 🐾 Replaces URL wildcards with an object of `params`.
|
|
11
12
|
- 🧙♀️ Automatically stringifies the `body` of a request so you can give it a JSON-like structure.
|
|
12
13
|
- 🐛 Accepts a `trace` function for debugging.
|
|
13
14
|
|
|
@@ -76,7 +77,7 @@ Its [`typedResponse`](#typedresponse) can also be parsed with a zod schema. Here
|
|
|
76
77
|
```ts
|
|
77
78
|
const response = await api.get("/users", {
|
|
78
79
|
query: { search: "John" },
|
|
79
|
-
trace: (
|
|
80
|
+
trace: (url, requestInit) => console.log(url, requestInit),
|
|
80
81
|
})
|
|
81
82
|
const json = await response.json(
|
|
82
83
|
z.object({
|
|
@@ -104,6 +105,38 @@ await api.head("/users")
|
|
|
104
105
|
await api.options("/users")
|
|
105
106
|
```
|
|
106
107
|
|
|
108
|
+
This function can also correctly merge any sort of `URL`, `URLSearchParams`, and `Headers`.
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
import { makeService } from 'make-service'
|
|
112
|
+
|
|
113
|
+
const api = makeService(new URL("https://example.com/api"), new Headers({
|
|
114
|
+
authorization: "Bearer 123"
|
|
115
|
+
}))
|
|
116
|
+
|
|
117
|
+
const response = await api.get("/users?admin=true", {
|
|
118
|
+
headers: [['accept', 'application/json']],
|
|
119
|
+
query: { page: "2" },
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
// It will call "https://example.com/api/users?admin=true&page=2"
|
|
123
|
+
// with headers: { authorization: "Bearer 123", accept: "application/json" }
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
In case you want to delete a header previously set you can pass `undefined` or `'undefined'` as its value:
|
|
127
|
+
```ts
|
|
128
|
+
const api = makeService("https://example.com/api", { authorization: "Bearer 123" })
|
|
129
|
+
const response = await api.get("/users", {
|
|
130
|
+
headers: new Headers({ authorization: 'undefined', "Content-Type": undefined }),
|
|
131
|
+
})
|
|
132
|
+
// headers will be empty.
|
|
133
|
+
```
|
|
134
|
+
Note: Don't forget headers are case insensitive.
|
|
135
|
+
```ts
|
|
136
|
+
const headers = new Headers({ 'Content-Type': 'application/json' })
|
|
137
|
+
Object.fromEntries(headers) // equals to: { 'content-type': 'application/json' }
|
|
138
|
+
```
|
|
139
|
+
|
|
107
140
|
## enhancedFetch
|
|
108
141
|
|
|
109
142
|
A wrapper around the `fetch` API.
|
|
@@ -121,22 +154,23 @@ const json = await response.json()
|
|
|
121
154
|
// You can pass it a generic or schema to type the result
|
|
122
155
|
```
|
|
123
156
|
|
|
124
|
-
This function accepts the same arguments as the `fetch` API - with exception of [JSON-like body](/src/make-service.ts) -, and it also accepts an object-like [`query`](/src/make-service.ts) and a `trace` function that will be called with the `
|
|
157
|
+
This function accepts the same arguments as the `fetch` API - with exception of [JSON-like body](/src/make-service.ts) -, and it also accepts an object of `params` to replace URL wildcards, an object-like [`query`](/src/make-service.ts) and a `trace` function that will be called with the `url` and `requestInit` arguments.
|
|
125
158
|
|
|
126
159
|
This slightly different `RequestInit` is typed as `EnhancedRequestInit`.
|
|
127
160
|
|
|
128
161
|
```ts
|
|
129
162
|
import { enhancedFetch } from 'make-service'
|
|
130
163
|
|
|
131
|
-
await enhancedFetch("https://example.com/api/users", {
|
|
164
|
+
await enhancedFetch("https://example.com/api/users/:role", {
|
|
132
165
|
method: 'POST',
|
|
133
166
|
body: { some: { object: { as: { body } } } },
|
|
134
167
|
query: { page: "1" },
|
|
135
|
-
|
|
168
|
+
params: { role: "admin" },
|
|
169
|
+
trace: (url, requestInit) => console.log(url, requestInit)
|
|
136
170
|
})
|
|
137
171
|
|
|
138
172
|
// The trace function will be called with the following arguments:
|
|
139
|
-
// "https://example.com/api/users?page=1"
|
|
173
|
+
// "https://example.com/api/users/admin?page=1"
|
|
140
174
|
// {
|
|
141
175
|
// method: 'POST',
|
|
142
176
|
// body: '{"some":{"object":{"as":{"body":{}}}}}',
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
declare const HTTP_METHODS: readonly ["
|
|
1
|
+
declare const HTTP_METHODS: readonly ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS", "HEAD"];
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* It returns the JSON object or throws an error if the response is not ok.
|
|
@@ -24,14 +24,24 @@ type TypedResponse = Omit<Response, 'json' | 'text'> & {
|
|
|
24
24
|
text: TypedResponseText;
|
|
25
25
|
};
|
|
26
26
|
type EnhancedRequestInit = Omit<RequestInit, 'body'> & {
|
|
27
|
-
body?: JSONValue;
|
|
27
|
+
body?: JSONValue | BodyInit | null;
|
|
28
28
|
query?: SearchParams;
|
|
29
|
+
params?: Record<string, string>;
|
|
29
30
|
trace?: (...args: Parameters<typeof fetch>) => void;
|
|
30
31
|
};
|
|
31
32
|
type ServiceRequestInit = Omit<EnhancedRequestInit, 'method'>;
|
|
32
33
|
type HTTPMethod = (typeof HTTP_METHODS)[number];
|
|
33
34
|
type TypedResponseJson = ReturnType<typeof getJson>;
|
|
34
35
|
type TypedResponseText = ReturnType<typeof getText>;
|
|
36
|
+
type Prettify<T> = {
|
|
37
|
+
[K in keyof T]: T[K];
|
|
38
|
+
} & {};
|
|
39
|
+
type NoEmpty<T> = keyof T extends never ? never : T;
|
|
40
|
+
type PathParams<T extends string> = NoEmpty<T extends `${infer _}:${infer Param}/${infer Rest}` ? Prettify<{
|
|
41
|
+
[K in Param]: string;
|
|
42
|
+
} & PathParams<Rest>> : T extends `${infer _}:${infer Param}` ? {
|
|
43
|
+
[K in Param]: string;
|
|
44
|
+
} : {}>;
|
|
35
45
|
|
|
36
46
|
/**
|
|
37
47
|
* It merges multiple HeadersInit objects into a single Headers object
|
|
@@ -40,11 +50,11 @@ type TypedResponseText = ReturnType<typeof getText>;
|
|
|
40
50
|
*/
|
|
41
51
|
declare function mergeHeaders(...entries: (HeadersInit | [string, undefined][] | Record<string, undefined>)[]): Headers;
|
|
42
52
|
/**
|
|
43
|
-
* @param
|
|
53
|
+
* @param url a string or URL to which the query parameters will be added
|
|
44
54
|
* @param searchParams the query parameters
|
|
45
|
-
* @returns the
|
|
55
|
+
* @returns the url with the query parameters added with the same type as the url
|
|
46
56
|
*/
|
|
47
|
-
declare function
|
|
57
|
+
declare function addQueryToUrl(url: string | URL, searchParams?: SearchParams): string | URL;
|
|
48
58
|
/**
|
|
49
59
|
* @param baseURL the base path to the API
|
|
50
60
|
* @returns a function that receives a path and an object of query parameters and returns a URL
|
|
@@ -67,12 +77,12 @@ declare function makeGetApiUrl(baseURL: string | URL): (path: string, searchPara
|
|
|
67
77
|
declare function typedResponse(response: Response): TypedResponse;
|
|
68
78
|
/**
|
|
69
79
|
* @param body the JSON-like body of the request
|
|
70
|
-
* @returns the body stringified if it is not a string
|
|
80
|
+
* @returns the body is stringified if it is not a string and it is a JSON-like object. It also accepts other types of BodyInit such as Blob, ReadableStream, etc.
|
|
71
81
|
*/
|
|
72
|
-
declare function ensureStringBody(body?:
|
|
82
|
+
declare function ensureStringBody<B extends JSONValue | BodyInit | null>(body?: B): B extends JSONValue ? string : B;
|
|
73
83
|
/**
|
|
74
84
|
*
|
|
75
|
-
* @param
|
|
85
|
+
* @param url a string or URL to be fetched
|
|
76
86
|
* @param requestInit the requestInit to be passed to the fetch request. It is the same as the `RequestInit` type, but it also accepts a JSON-like `body` and an object-like `query` parameter.
|
|
77
87
|
* @param requestInit.body the body of the request. It will be automatically stringified so you can send a JSON-like object
|
|
78
88
|
* @param requestInit.query the query parameters to be added to the URL
|
|
@@ -84,7 +94,7 @@ declare function ensureStringBody(body?: JSONValue): string | undefined;
|
|
|
84
94
|
* const untyped = await response.json();
|
|
85
95
|
* // ^? unknown
|
|
86
96
|
*/
|
|
87
|
-
declare function enhancedFetch(
|
|
97
|
+
declare function enhancedFetch(url: string | URL, requestInit?: EnhancedRequestInit): Promise<TypedResponse>;
|
|
88
98
|
/**
|
|
89
99
|
*
|
|
90
100
|
* @param baseURL the base URL to the API
|
|
@@ -96,14 +106,6 @@ declare function enhancedFetch(input: string | URL, requestInit?: EnhancedReques
|
|
|
96
106
|
* const users = await response.json(userSchema);
|
|
97
107
|
* // ^? User[]
|
|
98
108
|
*/
|
|
99
|
-
declare function makeService(baseURL: string | URL, baseHeaders?: HeadersInit):
|
|
100
|
-
get: (path: string, requestInit?: ServiceRequestInit) => Promise<TypedResponse>;
|
|
101
|
-
post: (path: string, requestInit?: ServiceRequestInit) => Promise<TypedResponse>;
|
|
102
|
-
put: (path: string, requestInit?: ServiceRequestInit) => Promise<TypedResponse>;
|
|
103
|
-
delete: (path: string, requestInit?: ServiceRequestInit) => Promise<TypedResponse>;
|
|
104
|
-
patch: (path: string, requestInit?: ServiceRequestInit) => Promise<TypedResponse>;
|
|
105
|
-
options: (path: string, requestInit?: ServiceRequestInit) => Promise<TypedResponse>;
|
|
106
|
-
head: (path: string, requestInit?: ServiceRequestInit) => Promise<TypedResponse>;
|
|
107
|
-
};
|
|
109
|
+
declare function makeService(baseURL: string | URL, baseHeaders?: HeadersInit | (() => HeadersInit | Promise<HeadersInit>)): Record<"delete" | "get" | "post" | "put" | "patch" | "options" | "head", (path: string, requestInit?: ServiceRequestInit) => Promise<TypedResponse>>;
|
|
108
110
|
|
|
109
|
-
export { EnhancedRequestInit, HTTPMethod, JSONValue, Schema, SearchParams, ServiceRequestInit, TypedResponse, TypedResponseJson, TypedResponseText,
|
|
111
|
+
export { EnhancedRequestInit, HTTPMethod, JSONValue, PathParams, Schema, SearchParams, ServiceRequestInit, TypedResponse, TypedResponseJson, TypedResponseText, addQueryToUrl, enhancedFetch, ensureStringBody, makeGetApiUrl, makeService, mergeHeaders, typedResponse };
|
package/dist/index.js
CHANGED
|
@@ -20,7 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var src_exports = {};
|
|
22
22
|
__export(src_exports, {
|
|
23
|
-
|
|
23
|
+
addQueryToUrl: () => addQueryToUrl,
|
|
24
24
|
enhancedFetch: () => enhancedFetch,
|
|
25
25
|
ensureStringBody: () => ensureStringBody,
|
|
26
26
|
makeGetApiUrl: () => makeGetApiUrl,
|
|
@@ -32,21 +32,18 @@ module.exports = __toCommonJS(src_exports);
|
|
|
32
32
|
|
|
33
33
|
// src/constants.ts
|
|
34
34
|
var HTTP_METHODS = [
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
35
|
+
"GET",
|
|
36
|
+
"POST",
|
|
37
|
+
"PUT",
|
|
38
|
+
"DELETE",
|
|
39
|
+
"PATCH",
|
|
40
|
+
"OPTIONS",
|
|
41
|
+
"HEAD"
|
|
42
42
|
];
|
|
43
43
|
|
|
44
44
|
// src/internals.ts
|
|
45
45
|
function getJson(response) {
|
|
46
46
|
return async (schema) => {
|
|
47
|
-
if (!response.ok) {
|
|
48
|
-
throw new Error(await response.text());
|
|
49
|
-
}
|
|
50
47
|
const json = await response.json();
|
|
51
48
|
return schema ? schema.parse(json) : json;
|
|
52
49
|
};
|
|
@@ -57,8 +54,17 @@ function getText(response) {
|
|
|
57
54
|
return schema ? schema.parse(text) : text;
|
|
58
55
|
};
|
|
59
56
|
}
|
|
60
|
-
function
|
|
61
|
-
|
|
57
|
+
function replaceUrlParams(url, params) {
|
|
58
|
+
if (!params)
|
|
59
|
+
return url;
|
|
60
|
+
let urlString = String(url);
|
|
61
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
62
|
+
urlString = urlString.replace(new RegExp(`:${key}($|/)`), `${value}$1`);
|
|
63
|
+
});
|
|
64
|
+
return url instanceof URL ? new URL(urlString) : urlString;
|
|
65
|
+
}
|
|
66
|
+
function typeOf(t) {
|
|
67
|
+
return Object.prototype.toString.call(t).replace(/^\[object (.+)\]$/, "$1").toLowerCase();
|
|
62
68
|
}
|
|
63
69
|
|
|
64
70
|
// src/make-service.ts
|
|
@@ -76,27 +82,27 @@ function mergeHeaders(...entries) {
|
|
|
76
82
|
}
|
|
77
83
|
return new Headers(Array.from(result.entries()));
|
|
78
84
|
}
|
|
79
|
-
function
|
|
85
|
+
function addQueryToUrl(url, searchParams) {
|
|
80
86
|
if (!searchParams)
|
|
81
|
-
return
|
|
82
|
-
if (typeof
|
|
83
|
-
const separator =
|
|
84
|
-
return `${
|
|
87
|
+
return url;
|
|
88
|
+
if (typeof url === "string") {
|
|
89
|
+
const separator = url.includes("?") ? "&" : "?";
|
|
90
|
+
return `${url}${separator}${new URLSearchParams(searchParams)}`;
|
|
85
91
|
}
|
|
86
|
-
if (searchParams &&
|
|
92
|
+
if (searchParams && url instanceof URL) {
|
|
87
93
|
for (const [key, value] of Object.entries(
|
|
88
94
|
new URLSearchParams(searchParams)
|
|
89
95
|
)) {
|
|
90
|
-
|
|
96
|
+
url.searchParams.set(key, value);
|
|
91
97
|
}
|
|
92
98
|
}
|
|
93
|
-
return
|
|
99
|
+
return url;
|
|
94
100
|
}
|
|
95
101
|
function makeGetApiUrl(baseURL) {
|
|
96
102
|
const base = baseURL instanceof URL ? baseURL.toString() : baseURL;
|
|
97
103
|
return (path, searchParams) => {
|
|
98
104
|
const url = `${base}${path}`.replace(/([^https?:]\/)\/+/g, "$1");
|
|
99
|
-
return
|
|
105
|
+
return addQueryToUrl(url, searchParams);
|
|
100
106
|
};
|
|
101
107
|
}
|
|
102
108
|
function typedResponse(response) {
|
|
@@ -112,13 +118,13 @@ function typedResponse(response) {
|
|
|
112
118
|
}
|
|
113
119
|
function ensureStringBody(body) {
|
|
114
120
|
if (typeof body === "undefined")
|
|
115
|
-
return;
|
|
121
|
+
return body;
|
|
116
122
|
if (typeof body === "string")
|
|
117
123
|
return body;
|
|
118
|
-
return JSON.stringify(body);
|
|
124
|
+
return ["number", "boolean", "array", "object"].includes(typeOf(body)) ? JSON.stringify(body) : body;
|
|
119
125
|
}
|
|
120
|
-
async function enhancedFetch(
|
|
121
|
-
var _a;
|
|
126
|
+
async function enhancedFetch(url, requestInit) {
|
|
127
|
+
var _a, _b;
|
|
122
128
|
const { query, trace, ...reqInit } = requestInit != null ? requestInit : {};
|
|
123
129
|
const headers = mergeHeaders(
|
|
124
130
|
{
|
|
@@ -126,11 +132,12 @@ async function enhancedFetch(input, requestInit) {
|
|
|
126
132
|
},
|
|
127
133
|
(_a = reqInit.headers) != null ? _a : {}
|
|
128
134
|
);
|
|
129
|
-
const
|
|
135
|
+
const withParams = replaceUrlParams(url, (_b = reqInit.params) != null ? _b : {});
|
|
136
|
+
const fullUrl = addQueryToUrl(withParams, query);
|
|
130
137
|
const body = ensureStringBody(reqInit.body);
|
|
131
138
|
const enhancedReqInit = { ...reqInit, headers, body };
|
|
132
|
-
trace == null ? void 0 : trace(
|
|
133
|
-
const response = await fetch(
|
|
139
|
+
trace == null ? void 0 : trace(fullUrl, enhancedReqInit);
|
|
140
|
+
const response = await fetch(fullUrl, enhancedReqInit);
|
|
134
141
|
return typedResponse(response);
|
|
135
142
|
}
|
|
136
143
|
function makeService(baseURL, baseHeaders) {
|
|
@@ -141,22 +148,24 @@ function makeService(baseURL, baseHeaders) {
|
|
|
141
148
|
const response = await enhancedFetch(url, {
|
|
142
149
|
...requestInit,
|
|
143
150
|
method,
|
|
144
|
-
headers: mergeHeaders(
|
|
151
|
+
headers: mergeHeaders(
|
|
152
|
+
typeof baseHeaders === "function" ? await baseHeaders() : baseHeaders != null ? baseHeaders : {},
|
|
153
|
+
(_a = requestInit == null ? void 0 : requestInit.headers) != null ? _a : {}
|
|
154
|
+
)
|
|
145
155
|
});
|
|
146
156
|
return response;
|
|
147
157
|
};
|
|
148
158
|
};
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
});
|
|
159
|
+
let api = {};
|
|
160
|
+
for (const method of HTTP_METHODS) {
|
|
161
|
+
const lowerMethod = method.toLowerCase();
|
|
162
|
+
api[lowerMethod] = service(method);
|
|
163
|
+
}
|
|
164
|
+
return api;
|
|
156
165
|
}
|
|
157
166
|
// Annotate the CommonJS export names for ESM import in node:
|
|
158
167
|
0 && (module.exports = {
|
|
159
|
-
|
|
168
|
+
addQueryToUrl,
|
|
160
169
|
enhancedFetch,
|
|
161
170
|
ensureStringBody,
|
|
162
171
|
makeGetApiUrl,
|
package/dist/index.mjs
CHANGED
|
@@ -1,20 +1,17 @@
|
|
|
1
1
|
// src/constants.ts
|
|
2
2
|
var HTTP_METHODS = [
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
3
|
+
"GET",
|
|
4
|
+
"POST",
|
|
5
|
+
"PUT",
|
|
6
|
+
"DELETE",
|
|
7
|
+
"PATCH",
|
|
8
|
+
"OPTIONS",
|
|
9
|
+
"HEAD"
|
|
10
10
|
];
|
|
11
11
|
|
|
12
12
|
// src/internals.ts
|
|
13
13
|
function getJson(response) {
|
|
14
14
|
return async (schema) => {
|
|
15
|
-
if (!response.ok) {
|
|
16
|
-
throw new Error(await response.text());
|
|
17
|
-
}
|
|
18
15
|
const json = await response.json();
|
|
19
16
|
return schema ? schema.parse(json) : json;
|
|
20
17
|
};
|
|
@@ -25,8 +22,17 @@ function getText(response) {
|
|
|
25
22
|
return schema ? schema.parse(text) : text;
|
|
26
23
|
};
|
|
27
24
|
}
|
|
28
|
-
function
|
|
29
|
-
|
|
25
|
+
function replaceUrlParams(url, params) {
|
|
26
|
+
if (!params)
|
|
27
|
+
return url;
|
|
28
|
+
let urlString = String(url);
|
|
29
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
30
|
+
urlString = urlString.replace(new RegExp(`:${key}($|/)`), `${value}$1`);
|
|
31
|
+
});
|
|
32
|
+
return url instanceof URL ? new URL(urlString) : urlString;
|
|
33
|
+
}
|
|
34
|
+
function typeOf(t) {
|
|
35
|
+
return Object.prototype.toString.call(t).replace(/^\[object (.+)\]$/, "$1").toLowerCase();
|
|
30
36
|
}
|
|
31
37
|
|
|
32
38
|
// src/make-service.ts
|
|
@@ -44,27 +50,27 @@ function mergeHeaders(...entries) {
|
|
|
44
50
|
}
|
|
45
51
|
return new Headers(Array.from(result.entries()));
|
|
46
52
|
}
|
|
47
|
-
function
|
|
53
|
+
function addQueryToUrl(url, searchParams) {
|
|
48
54
|
if (!searchParams)
|
|
49
|
-
return
|
|
50
|
-
if (typeof
|
|
51
|
-
const separator =
|
|
52
|
-
return `${
|
|
55
|
+
return url;
|
|
56
|
+
if (typeof url === "string") {
|
|
57
|
+
const separator = url.includes("?") ? "&" : "?";
|
|
58
|
+
return `${url}${separator}${new URLSearchParams(searchParams)}`;
|
|
53
59
|
}
|
|
54
|
-
if (searchParams &&
|
|
60
|
+
if (searchParams && url instanceof URL) {
|
|
55
61
|
for (const [key, value] of Object.entries(
|
|
56
62
|
new URLSearchParams(searchParams)
|
|
57
63
|
)) {
|
|
58
|
-
|
|
64
|
+
url.searchParams.set(key, value);
|
|
59
65
|
}
|
|
60
66
|
}
|
|
61
|
-
return
|
|
67
|
+
return url;
|
|
62
68
|
}
|
|
63
69
|
function makeGetApiUrl(baseURL) {
|
|
64
70
|
const base = baseURL instanceof URL ? baseURL.toString() : baseURL;
|
|
65
71
|
return (path, searchParams) => {
|
|
66
72
|
const url = `${base}${path}`.replace(/([^https?:]\/)\/+/g, "$1");
|
|
67
|
-
return
|
|
73
|
+
return addQueryToUrl(url, searchParams);
|
|
68
74
|
};
|
|
69
75
|
}
|
|
70
76
|
function typedResponse(response) {
|
|
@@ -80,13 +86,13 @@ function typedResponse(response) {
|
|
|
80
86
|
}
|
|
81
87
|
function ensureStringBody(body) {
|
|
82
88
|
if (typeof body === "undefined")
|
|
83
|
-
return;
|
|
89
|
+
return body;
|
|
84
90
|
if (typeof body === "string")
|
|
85
91
|
return body;
|
|
86
|
-
return JSON.stringify(body);
|
|
92
|
+
return ["number", "boolean", "array", "object"].includes(typeOf(body)) ? JSON.stringify(body) : body;
|
|
87
93
|
}
|
|
88
|
-
async function enhancedFetch(
|
|
89
|
-
var _a;
|
|
94
|
+
async function enhancedFetch(url, requestInit) {
|
|
95
|
+
var _a, _b;
|
|
90
96
|
const { query, trace, ...reqInit } = requestInit != null ? requestInit : {};
|
|
91
97
|
const headers = mergeHeaders(
|
|
92
98
|
{
|
|
@@ -94,11 +100,12 @@ async function enhancedFetch(input, requestInit) {
|
|
|
94
100
|
},
|
|
95
101
|
(_a = reqInit.headers) != null ? _a : {}
|
|
96
102
|
);
|
|
97
|
-
const
|
|
103
|
+
const withParams = replaceUrlParams(url, (_b = reqInit.params) != null ? _b : {});
|
|
104
|
+
const fullUrl = addQueryToUrl(withParams, query);
|
|
98
105
|
const body = ensureStringBody(reqInit.body);
|
|
99
106
|
const enhancedReqInit = { ...reqInit, headers, body };
|
|
100
|
-
trace == null ? void 0 : trace(
|
|
101
|
-
const response = await fetch(
|
|
107
|
+
trace == null ? void 0 : trace(fullUrl, enhancedReqInit);
|
|
108
|
+
const response = await fetch(fullUrl, enhancedReqInit);
|
|
102
109
|
return typedResponse(response);
|
|
103
110
|
}
|
|
104
111
|
function makeService(baseURL, baseHeaders) {
|
|
@@ -109,21 +116,23 @@ function makeService(baseURL, baseHeaders) {
|
|
|
109
116
|
const response = await enhancedFetch(url, {
|
|
110
117
|
...requestInit,
|
|
111
118
|
method,
|
|
112
|
-
headers: mergeHeaders(
|
|
119
|
+
headers: mergeHeaders(
|
|
120
|
+
typeof baseHeaders === "function" ? await baseHeaders() : baseHeaders != null ? baseHeaders : {},
|
|
121
|
+
(_a = requestInit == null ? void 0 : requestInit.headers) != null ? _a : {}
|
|
122
|
+
)
|
|
113
123
|
});
|
|
114
124
|
return response;
|
|
115
125
|
};
|
|
116
126
|
};
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
});
|
|
127
|
+
let api = {};
|
|
128
|
+
for (const method of HTTP_METHODS) {
|
|
129
|
+
const lowerMethod = method.toLowerCase();
|
|
130
|
+
api[lowerMethod] = service(method);
|
|
131
|
+
}
|
|
132
|
+
return api;
|
|
124
133
|
}
|
|
125
134
|
export {
|
|
126
|
-
|
|
135
|
+
addQueryToUrl,
|
|
127
136
|
enhancedFetch,
|
|
128
137
|
ensureStringBody,
|
|
129
138
|
makeGetApiUrl,
|
package/package.json
CHANGED