@ribbon-studios/js-utils 1.1.1 → 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 +95 -0
- package/dist/__tests__/rfetch.spec.d.ts +1 -0
- package/dist/index.cjs +78 -0
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +79 -1
- package/dist/rfetch.d.ts +65 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,6 +19,13 @@ Collection of generic javascript utilities curated by the Rainbow Cafe~
|
|
|
19
19
|
- [`assert`](#assert)
|
|
20
20
|
- [`assert.defined`](#assertdefined)
|
|
21
21
|
- [`never`](#never)
|
|
22
|
+
- [Fetch](#fetch)
|
|
23
|
+
- [`rfetch`](#rfetch)
|
|
24
|
+
- [`rfetch.get`](#rfetchget)
|
|
25
|
+
- [`rfetch.put`](#rfetchput)
|
|
26
|
+
- [`rfetch.post`](#rfetchpost)
|
|
27
|
+
- [`rfetch.patch`](#rfetchpatch)
|
|
28
|
+
- [`rfetch.remove`](#rfetchremove)
|
|
22
29
|
|
|
23
30
|
## Promises
|
|
24
31
|
|
|
@@ -96,6 +103,94 @@ const promise = never(); // Returns a promise that never resolves
|
|
|
96
103
|
const promise = never(Promise.resolve('hello')); // Returns a promise that never resolves
|
|
97
104
|
```
|
|
98
105
|
|
|
106
|
+
## Fetch
|
|
107
|
+
|
|
108
|
+
### `rfetch`
|
|
109
|
+
|
|
110
|
+
Lightweight wrapper around fetch that automatically handles:
|
|
111
|
+
|
|
112
|
+
- Query Params
|
|
113
|
+
- Form Data & JSON bodies
|
|
114
|
+
- JSON Responses (fallsback to text)
|
|
115
|
+
- Type Casting
|
|
116
|
+
- Errors
|
|
117
|
+
|
|
118
|
+
```tsx
|
|
119
|
+
import { rfetch, type RibbonFetchError } from '@ribbon-studios/js-utils';
|
|
120
|
+
|
|
121
|
+
try {
|
|
122
|
+
const response = await rfetch<MyExpectedResponse>('https://ribbonstudios.com', {
|
|
123
|
+
params: {
|
|
124
|
+
hello: 'world',
|
|
125
|
+
},
|
|
126
|
+
body: {
|
|
127
|
+
hallo: 'welt',
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
console.log(response);
|
|
132
|
+
// => MyExpectedResponse
|
|
133
|
+
} catch (error: RibbonFetchError<MyExpectedErrorResponse>) {
|
|
134
|
+
console.error(error);
|
|
135
|
+
// => { status: number; content: MyExpectedErrorResponse; }
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### `rfetch.get`
|
|
140
|
+
|
|
141
|
+
Shorthand for GET requests.
|
|
142
|
+
|
|
143
|
+
```tsx
|
|
144
|
+
import { rfetch, type RibbonFetchError } from '@ribbon-studios/js-utils';
|
|
145
|
+
|
|
146
|
+
// Shorthand for GET requests.
|
|
147
|
+
await rfetch.get<MyExpectedResponse>('https://ribbonstudios.com');
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### `rfetch.put`
|
|
151
|
+
|
|
152
|
+
Shorthand for PUT requests.
|
|
153
|
+
|
|
154
|
+
```tsx
|
|
155
|
+
import { rfetch, type RibbonFetchError } from '@ribbon-studios/js-utils';
|
|
156
|
+
|
|
157
|
+
// Shorthand for PUT requests.
|
|
158
|
+
await rfetch.put<MyExpectedResponse>('https://ribbonstudios.com');
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### `rfetch.post`
|
|
162
|
+
|
|
163
|
+
Shorthand for POST requests.
|
|
164
|
+
|
|
165
|
+
```tsx
|
|
166
|
+
import { rfetch, type RibbonFetchError } from '@ribbon-studios/js-utils';
|
|
167
|
+
|
|
168
|
+
// Shorthand for POST requests.
|
|
169
|
+
await rfetch.post<MyExpectedResponse>('https://ribbonstudios.com');
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### `rfetch.patch`
|
|
173
|
+
|
|
174
|
+
Shorthand for PATCH requests.
|
|
175
|
+
|
|
176
|
+
```tsx
|
|
177
|
+
import { rfetch, type RibbonFetchError } from '@ribbon-studios/js-utils';
|
|
178
|
+
|
|
179
|
+
// Shorthand for PATCH requests.
|
|
180
|
+
await rfetch.patch<MyExpectedResponse>('https://ribbonstudios.com');
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### `rfetch.remove`
|
|
184
|
+
|
|
185
|
+
Shorthand for DELETE requests.
|
|
186
|
+
|
|
187
|
+
```tsx
|
|
188
|
+
import { rfetch, type RibbonFetchError } from '@ribbon-studios/js-utils';
|
|
189
|
+
|
|
190
|
+
// Shorthand for DELETE requests.
|
|
191
|
+
await rfetch.remove<MyExpectedResponse>('https://ribbonstudios.com');
|
|
192
|
+
```
|
|
193
|
+
|
|
99
194
|
[_**Want to Contribute?**_](/CONTRIBUTING.md)
|
|
100
195
|
|
|
101
196
|
[npm-version-image]: https://img.shields.io/npm/v/@ribbon-studios/js-utils.svg
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.cjs
CHANGED
|
@@ -32,6 +32,84 @@ async function never(p) {
|
|
|
32
32
|
return new Promise(() => {
|
|
33
33
|
});
|
|
34
34
|
}
|
|
35
|
+
async function rfetch(url, options) {
|
|
36
|
+
var _a, _b;
|
|
37
|
+
const { params, headers, body, ...internalOptions } = {
|
|
38
|
+
method: "GET",
|
|
39
|
+
headers: {},
|
|
40
|
+
...options
|
|
41
|
+
};
|
|
42
|
+
const internalURL = url instanceof URL ? url : new URL(url, url.startsWith("/") ? location.origin : void 0);
|
|
43
|
+
if (params) {
|
|
44
|
+
for (const [key, values] of Object.entries(params)) {
|
|
45
|
+
if (Array.isArray(values)) {
|
|
46
|
+
for (const value of values) {
|
|
47
|
+
internalURL.searchParams.append(key, value.toString());
|
|
48
|
+
}
|
|
49
|
+
} else {
|
|
50
|
+
internalURL.searchParams.append(key, values.toString());
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
let internalBody = void 0;
|
|
55
|
+
if (body) {
|
|
56
|
+
internalBody = body instanceof FormData ? body : JSON.stringify(body);
|
|
57
|
+
}
|
|
58
|
+
const response = await fetch(internalURL, {
|
|
59
|
+
...internalOptions,
|
|
60
|
+
headers: {
|
|
61
|
+
"Content-Type": internalBody instanceof FormData ? "application/x-www-form-urlencoded" : "application/json",
|
|
62
|
+
...headers
|
|
63
|
+
},
|
|
64
|
+
body: internalBody
|
|
65
|
+
});
|
|
66
|
+
const content = ((_b = (_a = response.headers.get("Content-Type")) == null ? void 0 : _a.toLowerCase()) == null ? void 0 : _b.includes("json")) ? await response.json() : await response.text();
|
|
67
|
+
if (response.ok) {
|
|
68
|
+
return content;
|
|
69
|
+
}
|
|
70
|
+
return Promise.reject({
|
|
71
|
+
status: response.status,
|
|
72
|
+
content
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
((rfetch2) => {
|
|
76
|
+
async function get(url, options) {
|
|
77
|
+
return rfetch2(url, {
|
|
78
|
+
...options,
|
|
79
|
+
method: "GET"
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
rfetch2.get = get;
|
|
83
|
+
async function put(url, options) {
|
|
84
|
+
return rfetch2(url, {
|
|
85
|
+
...options,
|
|
86
|
+
method: "PUT"
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
rfetch2.put = put;
|
|
90
|
+
async function post(url, options) {
|
|
91
|
+
return rfetch2(url, {
|
|
92
|
+
...options,
|
|
93
|
+
method: "POST"
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
rfetch2.post = post;
|
|
97
|
+
async function patch(url, options) {
|
|
98
|
+
return rfetch2(url, {
|
|
99
|
+
...options,
|
|
100
|
+
method: "PATCH"
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
rfetch2.patch = patch;
|
|
104
|
+
async function remove(url, options) {
|
|
105
|
+
return rfetch2(url, {
|
|
106
|
+
...options,
|
|
107
|
+
method: "DELETE"
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
rfetch2.remove = remove;
|
|
111
|
+
})(rfetch || (rfetch = {}));
|
|
35
112
|
exports.assert = assert;
|
|
36
113
|
exports.delay = delay;
|
|
37
114
|
exports.never = never;
|
|
115
|
+
exports.rfetch = rfetch;
|
package/dist/index.d.cts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -30,8 +30,86 @@ async function never(p) {
|
|
|
30
30
|
return new Promise(() => {
|
|
31
31
|
});
|
|
32
32
|
}
|
|
33
|
+
async function rfetch(url, options) {
|
|
34
|
+
var _a, _b;
|
|
35
|
+
const { params, headers, body, ...internalOptions } = {
|
|
36
|
+
method: "GET",
|
|
37
|
+
headers: {},
|
|
38
|
+
...options
|
|
39
|
+
};
|
|
40
|
+
const internalURL = url instanceof URL ? url : new URL(url, url.startsWith("/") ? location.origin : void 0);
|
|
41
|
+
if (params) {
|
|
42
|
+
for (const [key, values] of Object.entries(params)) {
|
|
43
|
+
if (Array.isArray(values)) {
|
|
44
|
+
for (const value of values) {
|
|
45
|
+
internalURL.searchParams.append(key, value.toString());
|
|
46
|
+
}
|
|
47
|
+
} else {
|
|
48
|
+
internalURL.searchParams.append(key, values.toString());
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
let internalBody = void 0;
|
|
53
|
+
if (body) {
|
|
54
|
+
internalBody = body instanceof FormData ? body : JSON.stringify(body);
|
|
55
|
+
}
|
|
56
|
+
const response = await fetch(internalURL, {
|
|
57
|
+
...internalOptions,
|
|
58
|
+
headers: {
|
|
59
|
+
"Content-Type": internalBody instanceof FormData ? "application/x-www-form-urlencoded" : "application/json",
|
|
60
|
+
...headers
|
|
61
|
+
},
|
|
62
|
+
body: internalBody
|
|
63
|
+
});
|
|
64
|
+
const content = ((_b = (_a = response.headers.get("Content-Type")) == null ? void 0 : _a.toLowerCase()) == null ? void 0 : _b.includes("json")) ? await response.json() : await response.text();
|
|
65
|
+
if (response.ok) {
|
|
66
|
+
return content;
|
|
67
|
+
}
|
|
68
|
+
return Promise.reject({
|
|
69
|
+
status: response.status,
|
|
70
|
+
content
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
((rfetch2) => {
|
|
74
|
+
async function get(url, options) {
|
|
75
|
+
return rfetch2(url, {
|
|
76
|
+
...options,
|
|
77
|
+
method: "GET"
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
rfetch2.get = get;
|
|
81
|
+
async function put(url, options) {
|
|
82
|
+
return rfetch2(url, {
|
|
83
|
+
...options,
|
|
84
|
+
method: "PUT"
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
rfetch2.put = put;
|
|
88
|
+
async function post(url, options) {
|
|
89
|
+
return rfetch2(url, {
|
|
90
|
+
...options,
|
|
91
|
+
method: "POST"
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
rfetch2.post = post;
|
|
95
|
+
async function patch(url, options) {
|
|
96
|
+
return rfetch2(url, {
|
|
97
|
+
...options,
|
|
98
|
+
method: "PATCH"
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
rfetch2.patch = patch;
|
|
102
|
+
async function remove(url, options) {
|
|
103
|
+
return rfetch2(url, {
|
|
104
|
+
...options,
|
|
105
|
+
method: "DELETE"
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
rfetch2.remove = remove;
|
|
109
|
+
})(rfetch || (rfetch = {}));
|
|
33
110
|
export {
|
|
34
111
|
assert,
|
|
35
112
|
delay,
|
|
36
|
-
never
|
|
113
|
+
never,
|
|
114
|
+
rfetch
|
|
37
115
|
};
|
package/dist/rfetch.d.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
type RibbonFetchParamType = string | number | boolean;
|
|
2
|
+
export type RibbonFetchOptions = {
|
|
3
|
+
method?: 'GET' | 'PUT' | 'POST' | 'PATCH' | 'DELETE';
|
|
4
|
+
params?: Record<string, RibbonFetchParamType | RibbonFetchParamType[]>;
|
|
5
|
+
body?: any;
|
|
6
|
+
headers?: HeadersInit;
|
|
7
|
+
} & Omit<RequestInit, 'body' | 'headers' | 'method'>;
|
|
8
|
+
export type RibbonFetchBasicOptions = Omit<RibbonFetchOptions, 'method' | 'body'>;
|
|
9
|
+
export type RibbonFetchBodyOptions = Omit<RibbonFetchOptions, 'method'>;
|
|
10
|
+
export type RibbonFetchError<R> = {
|
|
11
|
+
status: number;
|
|
12
|
+
content: R;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* A lightweight wrapper around fetch to simplify its usage.
|
|
16
|
+
*
|
|
17
|
+
* @param url The url you wish to fetch.
|
|
18
|
+
* @param options The request options.
|
|
19
|
+
* @returns The typed response or an error containing the `status` and the `content`
|
|
20
|
+
*/
|
|
21
|
+
export declare function rfetch<T = any>(url: string | URL, options?: RibbonFetchOptions): Promise<T>;
|
|
22
|
+
export declare namespace rfetch {
|
|
23
|
+
/**
|
|
24
|
+
* Shorthand method for a GET request
|
|
25
|
+
*
|
|
26
|
+
* @param url The url you wish to fetch.
|
|
27
|
+
* @param options The request options.
|
|
28
|
+
* @returns The typed response or an error containing the `status` and the `content`
|
|
29
|
+
*/
|
|
30
|
+
function get<T>(url: string | URL, options?: RibbonFetchBasicOptions): Promise<T>;
|
|
31
|
+
/**
|
|
32
|
+
* Shorthand method for a PUT request
|
|
33
|
+
*
|
|
34
|
+
* @param url The url you wish to fetch.
|
|
35
|
+
* @param options The request options.
|
|
36
|
+
* @returns The typed response or an error containing the `status` and the `content`
|
|
37
|
+
*/
|
|
38
|
+
function put<T>(url: string | URL, options?: RibbonFetchBodyOptions): Promise<T>;
|
|
39
|
+
/**
|
|
40
|
+
* Shorthand method for a POST request
|
|
41
|
+
*
|
|
42
|
+
* @param url The url you wish to fetch.
|
|
43
|
+
* @param options The request options.
|
|
44
|
+
* @returns The typed response or an error containing the `status` and the `content`
|
|
45
|
+
*/
|
|
46
|
+
function post<T>(url: string | URL, options?: RibbonFetchBodyOptions): Promise<T>;
|
|
47
|
+
/**
|
|
48
|
+
* Shorthand method for a PATCH request
|
|
49
|
+
*
|
|
50
|
+
* @param url The url you wish to fetch.
|
|
51
|
+
* @param options The request options.
|
|
52
|
+
* @returns The typed response or an error containing the `status` and the `content`
|
|
53
|
+
*/
|
|
54
|
+
function patch<T>(url: string | URL, options?: RibbonFetchBodyOptions): Promise<T>;
|
|
55
|
+
/**
|
|
56
|
+
* Shorthand method for a DELETE request
|
|
57
|
+
*
|
|
58
|
+
* @param url The url you wish to fetch.
|
|
59
|
+
* @param options The request options.
|
|
60
|
+
* @returns The typed response or an error containing the `status` and the `content`
|
|
61
|
+
* @note This is named `remove` purely because `delete` is a reserved key
|
|
62
|
+
*/
|
|
63
|
+
function remove<T>(url: string | URL, options?: RibbonFetchBodyOptions): Promise<T>;
|
|
64
|
+
}
|
|
65
|
+
export {};
|