make-service 0.0.2 → 0.0.3

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 CHANGED
@@ -40,9 +40,9 @@ This library exports the `makeService` function and some primitives used to buil
40
40
 
41
41
  # makeService
42
42
 
43
- The main function of this lib is built on top of the primitives described in the following sections. It allows you to create an "API" object with a `baseURL` and common `headers` for every request.
43
+ The main function of this lib is built on top of the primitives described in the following sections. It allows you to create a service object with a `baseURL` and common `headers` for every request.
44
44
 
45
- This "api" object can be called with every HTTP method and it will return a [`typedResponse`](#typedresponse) object as it uses the [`enhancedFetch`](#enhancedfetch) internally.
45
+ This service object can be called with every HTTP method and it will return a [`typedResponse`](#typedresponse) object as it uses the [`enhancedFetch`](#enhancedfetch) internally.
46
46
 
47
47
  ```ts
48
48
  import { makeService } from 'make-service'
@@ -107,7 +107,7 @@ await api.options("/users")
107
107
  ## enhancedFetch
108
108
 
109
109
  A wrapper around the `fetch` API.
110
- It returns a [`typedResponse`](#typedresponse) instead of a `Response`.
110
+ It returns a [`TypedResponse`](#typedresponse) instead of a `Response`.
111
111
 
112
112
  ```ts
113
113
  import { enhancedFetch } from 'make-service'
@@ -123,6 +123,8 @@ const json = await response.json()
123
123
 
124
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 `input` and `requestInit` arguments.
125
125
 
126
+ This slightly different `RequestInit` is typed as `EnhancedRequestInit`.
127
+
126
128
  ```ts
127
129
  import { enhancedFetch } from 'make-service'
128
130
 
@@ -150,9 +152,10 @@ A type-safe wrapper around the `Response` object. It adds a `json` and `text` me
150
152
 
151
153
  ```ts
152
154
  import { typedResponse } from 'make-service'
155
+ import type { TypedResponse } from 'make-service'
153
156
 
154
157
  // With JSON
155
- const response = new Response(JSON.stringify({ foo: "bar" }))
158
+ const response: TypedResponse = new Response(JSON.stringify({ foo: "bar" }))
156
159
  const json = await typedResponse(response).json()
157
160
  // ^? unknown
158
161
  const json = await typedResponse(response).json<{ foo: string }>()
@@ -161,7 +164,7 @@ const json = await typedResponse(response).json(z.object({ foo: z.string() }))
161
164
  // ^? { foo: string }
162
165
 
163
166
  // With text
164
- const response = new Response("foo")
167
+ const response: TypedResponse = new Response("foo")
165
168
  const text = await typedResponse(response).text()
166
169
  // ^? string
167
170
  const text = await typedResponse(response).text<`foo${string}`>()
package/dist/index.d.ts CHANGED
@@ -1,10 +1,4 @@
1
- type Schema<T> = {
2
- parse: (d: unknown) => T;
3
- };
4
- type JSONValue = string | number | boolean | {
5
- [x: string]: JSONValue;
6
- } | Array<JSONValue>;
7
- type SearchParams = ConstructorParameters<typeof URLSearchParams>[0];
1
+ declare const HTTP_METHODS: readonly ["get", "post", "put", "delete", "patch", "options", "head"];
8
2
 
9
3
  /**
10
4
  * It returns the JSON object or throws an error if the response is not ok.
@@ -18,6 +12,27 @@ declare function getJson(response: Response): <T = unknown>(schema?: Schema<T> |
18
12
  */
19
13
  declare function getText(response: Response): <T extends string = string>(schema?: Schema<T> | undefined) => Promise<T>;
20
14
 
15
+ type Schema<T> = {
16
+ parse: (d: unknown) => T;
17
+ };
18
+ type JSONValue = string | number | boolean | {
19
+ [x: string]: JSONValue;
20
+ } | Array<JSONValue>;
21
+ type SearchParams = ConstructorParameters<typeof URLSearchParams>[0];
22
+ type TypedResponse = Omit<Response, 'json' | 'text'> & {
23
+ json: TypedResponseJson;
24
+ text: TypedResponseText;
25
+ };
26
+ type EnhancedRequestInit = Omit<RequestInit, 'body'> & {
27
+ body?: JSONValue;
28
+ query?: SearchParams;
29
+ trace?: (...args: Parameters<typeof fetch>) => void;
30
+ };
31
+ type ServiceRequestInit = Omit<EnhancedRequestInit, 'method'>;
32
+ type HTTPMethod = (typeof HTTP_METHODS)[number];
33
+ type TypedResponseJson = ReturnType<typeof getJson>;
34
+ type TypedResponseText = ReturnType<typeof getText>;
35
+
21
36
  /**
22
37
  * @param input a string or URL to which the query parameters will be added
23
38
  * @param searchParams the query parameters
@@ -43,27 +58,19 @@ declare function makeGetApiUrl(baseURL: string): (path: string, searchParams?: S
43
58
  * const typedJson = await response.json<User[]>();
44
59
  * // ^? User[]
45
60
  */
46
- declare function typedResponse(response: Response): Omit<Response, "json" | "text"> & {
47
- json: ReturnType<typeof getJson>;
48
- text: ReturnType<typeof getText>;
49
- };
61
+ declare function typedResponse(response: Response): TypedResponse;
50
62
  /**
51
63
  * @param body the JSON-like body of the request
52
64
  * @returns the body stringified if it is not a string
53
65
  */
54
66
  declare function ensureStringBody(body?: JSONValue): string | undefined;
55
- type Options = Omit<RequestInit, 'body'> & {
56
- body?: JSONValue;
57
- query?: SearchParams;
58
- trace?: (...args: Parameters<typeof fetch>) => void;
59
- };
60
67
  /**
61
68
  *
62
69
  * @param input a string or URL to be fetched
63
- * @param options the options 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.
64
- * @param options.body the body of the request. It will be automatically stringified so you can send a JSON-like object
65
- * @param options.query the query parameters to be added to the URL
66
- * @param options.trace a function that receives the URL and the requestInit and can be used to log the request
70
+ * @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.
71
+ * @param requestInit.body the body of the request. It will be automatically stringified so you can send a JSON-like object
72
+ * @param requestInit.query the query parameters to be added to the URL
73
+ * @param requestInit.trace a function that receives the URL and the requestInit and can be used to log the request
67
74
  * @returns a Response with typed json and text methods
68
75
  * @example const response = await fetch("https://example.com/api/users");
69
76
  * const users = await response.json(userSchema);
@@ -71,24 +78,26 @@ type Options = Omit<RequestInit, 'body'> & {
71
78
  * const untyped = await response.json();
72
79
  * // ^? unknown
73
80
  */
74
- declare function enhancedFetch(input: string | URL, options?: Options): Promise<Omit<Response, "json" | "text"> & {
75
- json: <T = unknown>(schema?: Schema<T> | undefined) => Promise<T>;
76
- text: <T_1 extends string = string>(schema?: Schema<T_1> | undefined) => Promise<T_1>;
77
- }>;
81
+ declare function enhancedFetch(input: string | URL, requestInit?: EnhancedRequestInit): Promise<TypedResponse>;
78
82
  /**
79
83
  *
80
84
  * @param baseURL the base URL to the API
81
85
  * @param baseHeaders any headers that should be sent with every request
82
- * @returns an API object with HTTP methods that are functions that receive a path and options and return a serialized json response that can be typed or not.
86
+ * @returns a service object with HTTP methods that are functions that receive a path and requestInit and return a serialized json response that can be typed or not.
83
87
  * @example const headers = { Authorization: "Bearer 123" }
84
88
  * const api = makeService("https://example.com/api", headers);
85
89
  * const response = await api.get("/users")
86
90
  * const users = await response.json(userSchema);
87
91
  * // ^? User[]
88
92
  */
89
- declare function makeService(baseURL: string, baseHeaders?: HeadersInit): Record<"get" | "post" | "put" | "delete" | "patch" | "options" | "head", (path: string, options?: Omit<Options, 'method'>) => Promise<Omit<Response, "json" | "text"> & {
90
- json: <T = unknown>(schema?: Schema<T> | undefined) => Promise<T>;
91
- text: <T_1 extends string = string>(schema?: Schema<T_1> | undefined) => Promise<T_1>;
92
- }>>;
93
+ declare function makeService(baseURL: string, baseHeaders?: HeadersInit): {
94
+ get: (path: string, requestInit?: ServiceRequestInit) => Promise<TypedResponse>;
95
+ post: (path: string, requestInit?: ServiceRequestInit) => Promise<TypedResponse>;
96
+ put: (path: string, requestInit?: ServiceRequestInit) => Promise<TypedResponse>;
97
+ delete: (path: string, requestInit?: ServiceRequestInit) => Promise<TypedResponse>;
98
+ patch: (path: string, requestInit?: ServiceRequestInit) => Promise<TypedResponse>;
99
+ options: (path: string, requestInit?: ServiceRequestInit) => Promise<TypedResponse>;
100
+ head: (path: string, requestInit?: ServiceRequestInit) => Promise<TypedResponse>;
101
+ };
93
102
 
94
- export { addQueryToInput, enhancedFetch, ensureStringBody, makeGetApiUrl, makeService, typedResponse };
103
+ export { EnhancedRequestInit, HTTPMethod, JSONValue, Schema, SearchParams, ServiceRequestInit, TypedResponse, TypedResponseJson, TypedResponseText, addQueryToInput, enhancedFetch, ensureStringBody, makeGetApiUrl, makeService, typedResponse };
package/dist/index.js CHANGED
@@ -94,24 +94,24 @@ function ensureStringBody(body) {
94
94
  return body;
95
95
  return JSON.stringify(body);
96
96
  }
97
- async function enhancedFetch(input, options) {
98
- const { query, trace, ...reqInit } = options != null ? options : {};
97
+ async function enhancedFetch(input, requestInit) {
98
+ const { query, trace, ...reqInit } = requestInit != null ? requestInit : {};
99
99
  const headers = { "content-type": "application/json", ...reqInit.headers };
100
100
  const url = addQueryToInput(input, query);
101
101
  const body = ensureStringBody(reqInit.body);
102
- const requestInit = { ...reqInit, headers, body };
103
- trace == null ? void 0 : trace(url, requestInit);
104
- const request = new Request(url, requestInit);
102
+ const enhancedReqInit = { ...reqInit, headers, body };
103
+ trace == null ? void 0 : trace(url, enhancedReqInit);
104
+ const request = new Request(url, enhancedReqInit);
105
105
  const response = await fetch(request);
106
106
  return typedResponse(response);
107
107
  }
108
108
  function makeService(baseURL, baseHeaders) {
109
- const api = (method) => {
110
- return async (path, options = {}) => {
109
+ const service = (method) => {
110
+ return async (path, requestInit = {}) => {
111
111
  const response = await enhancedFetch(`${baseURL}${path}`, {
112
- ...options,
112
+ ...requestInit,
113
113
  method,
114
- headers: { ...baseHeaders, ...options == null ? void 0 : options.headers }
114
+ headers: { ...baseHeaders, ...requestInit == null ? void 0 : requestInit.headers }
115
115
  });
116
116
  return response;
117
117
  };
@@ -119,7 +119,7 @@ function makeService(baseURL, baseHeaders) {
119
119
  return new Proxy({}, {
120
120
  get(_target, prop) {
121
121
  if (isHTTPMethod(prop))
122
- return api(prop);
122
+ return service(prop);
123
123
  throw new Error(`Invalid HTTP method: ${prop.toString()}`);
124
124
  }
125
125
  });
package/dist/index.mjs CHANGED
@@ -63,24 +63,24 @@ function ensureStringBody(body) {
63
63
  return body;
64
64
  return JSON.stringify(body);
65
65
  }
66
- async function enhancedFetch(input, options) {
67
- const { query, trace, ...reqInit } = options != null ? options : {};
66
+ async function enhancedFetch(input, requestInit) {
67
+ const { query, trace, ...reqInit } = requestInit != null ? requestInit : {};
68
68
  const headers = { "content-type": "application/json", ...reqInit.headers };
69
69
  const url = addQueryToInput(input, query);
70
70
  const body = ensureStringBody(reqInit.body);
71
- const requestInit = { ...reqInit, headers, body };
72
- trace == null ? void 0 : trace(url, requestInit);
73
- const request = new Request(url, requestInit);
71
+ const enhancedReqInit = { ...reqInit, headers, body };
72
+ trace == null ? void 0 : trace(url, enhancedReqInit);
73
+ const request = new Request(url, enhancedReqInit);
74
74
  const response = await fetch(request);
75
75
  return typedResponse(response);
76
76
  }
77
77
  function makeService(baseURL, baseHeaders) {
78
- const api = (method) => {
79
- return async (path, options = {}) => {
78
+ const service = (method) => {
79
+ return async (path, requestInit = {}) => {
80
80
  const response = await enhancedFetch(`${baseURL}${path}`, {
81
- ...options,
81
+ ...requestInit,
82
82
  method,
83
- headers: { ...baseHeaders, ...options == null ? void 0 : options.headers }
83
+ headers: { ...baseHeaders, ...requestInit == null ? void 0 : requestInit.headers }
84
84
  });
85
85
  return response;
86
86
  };
@@ -88,7 +88,7 @@ function makeService(baseURL, baseHeaders) {
88
88
  return new Proxy({}, {
89
89
  get(_target, prop) {
90
90
  if (isHTTPMethod(prop))
91
- return api(prop);
91
+ return service(prop);
92
92
  throw new Error(`Invalid HTTP method: ${prop.toString()}`);
93
93
  }
94
94
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "make-service",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "Some utilities to extend the 'fetch' API to better interact with external APIs.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",