floppy-disk 2.9.0-beta.2 → 2.10.0-beta.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/esm/index.d.ts +1 -0
- package/esm/index.js +1 -0
- package/esm/react/create-query.js +2 -2
- package/esm/utils/fetcher.d.ts +16 -0
- package/esm/utils/fetcher.js +69 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/react/create-query.js +2 -2
- package/lib/utils/fetcher.d.ts +16 -0
- package/lib/utils/fetcher.js +73 -0
- package/package.json +1 -1
package/esm/index.d.ts
CHANGED
package/esm/index.js
CHANGED
|
@@ -31,7 +31,7 @@ const useQueryDefaultDeps = (state) => [
|
|
|
31
31
|
state.isWaitingNextPage,
|
|
32
32
|
state.hasNextPage,
|
|
33
33
|
];
|
|
34
|
-
const
|
|
34
|
+
const fallbackComponent = () => null;
|
|
35
35
|
/**
|
|
36
36
|
* @see https://floppy-disk.vercel.app/docs/api#createquery
|
|
37
37
|
*/
|
|
@@ -408,7 +408,7 @@ export const createQuery = (queryFn, options = {}) => {
|
|
|
408
408
|
return state;
|
|
409
409
|
};
|
|
410
410
|
useQuery.Render = (props) => {
|
|
411
|
-
const { queryKey, loading =
|
|
411
|
+
const { queryKey, loading = fallbackComponent, success = fallbackComponent, error = fallbackComponent, } = props;
|
|
412
412
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
413
413
|
const state = useQuery(queryKey);
|
|
414
414
|
if (state.data)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
type FetcherOptions<TResponse = any> = {
|
|
2
|
+
url: string;
|
|
3
|
+
query?: string;
|
|
4
|
+
params?: Record<string, string | number | boolean> | null;
|
|
5
|
+
payload?: any;
|
|
6
|
+
validate?: (response: TResponse) => void | Promise<void>;
|
|
7
|
+
} & RequestInit;
|
|
8
|
+
/**
|
|
9
|
+
* Experimental fetcher - a query/mutation function creator.
|
|
10
|
+
*
|
|
11
|
+
* Can be used for REST or GraphQL.
|
|
12
|
+
*
|
|
13
|
+
* @returns A function to fetch data
|
|
14
|
+
*/
|
|
15
|
+
export declare const fetcher: <TResponse = any, TInput extends any[] = any[]>(options: FetcherOptions<TResponse> | ((...args: TInput) => FetcherOptions<TResponse>)) => (...args: TInput) => Promise<TResponse>;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/* eslint-disable no-throw-literal */
|
|
2
|
+
import { getValueOrComputedValue } from '.';
|
|
3
|
+
const encodeParams = (params) => Object.entries(params)
|
|
4
|
+
.map((kv) => kv.map(encodeURIComponent).join('='))
|
|
5
|
+
.join('&');
|
|
6
|
+
/**
|
|
7
|
+
* Experimental fetcher - a query/mutation function creator.
|
|
8
|
+
*
|
|
9
|
+
* Can be used for REST or GraphQL.
|
|
10
|
+
*
|
|
11
|
+
* @returns A function to fetch data
|
|
12
|
+
*/
|
|
13
|
+
export const fetcher = (options) => async (...args) => {
|
|
14
|
+
const { url, query, params, payload, headers, validate, ...rest } = getValueOrComputedValue(options, ...args);
|
|
15
|
+
let autoOptions = {};
|
|
16
|
+
let searchParams = params;
|
|
17
|
+
if (query) {
|
|
18
|
+
// GraphQL
|
|
19
|
+
autoOptions = {
|
|
20
|
+
method: 'POST',
|
|
21
|
+
body: JSON.stringify({ query, variables: payload || args[0] }),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
else if (rest.method && rest.method.toLowerCase() !== 'get') {
|
|
25
|
+
// REST - Mutation
|
|
26
|
+
autoOptions = {
|
|
27
|
+
body: JSON.stringify(payload === undefined ? args[0] : payload),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
// REST - Query
|
|
32
|
+
if (typeof options === 'object' && params === undefined)
|
|
33
|
+
searchParams = args[0];
|
|
34
|
+
}
|
|
35
|
+
const fetchUrl = searchParams ? [url, encodeParams(searchParams)].join('?') : url;
|
|
36
|
+
const res = await fetch(fetchUrl, {
|
|
37
|
+
headers: { 'Content-Type': 'application/json', ...headers },
|
|
38
|
+
...autoOptions,
|
|
39
|
+
...rest,
|
|
40
|
+
});
|
|
41
|
+
const contentType = res.headers.get('content-type');
|
|
42
|
+
if (contentType && contentType.includes('application/json')) {
|
|
43
|
+
const resJson = await res.json().catch(() => undefined);
|
|
44
|
+
if (resJson !== undefined) {
|
|
45
|
+
if (query && resJson.errors) {
|
|
46
|
+
throw { status: res.status, statusText: res.statusText, response: resJson };
|
|
47
|
+
}
|
|
48
|
+
if (res.ok) {
|
|
49
|
+
if (validate) {
|
|
50
|
+
try {
|
|
51
|
+
await validate(resJson);
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
throw {
|
|
55
|
+
status: res.status,
|
|
56
|
+
statusText: res.statusText,
|
|
57
|
+
response: resJson,
|
|
58
|
+
validationError: err,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return resJson;
|
|
63
|
+
}
|
|
64
|
+
throw { status: res.status, statusText: res.statusText, response: resJson };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const resText = await res.text().catch(() => undefined);
|
|
68
|
+
throw { status: res.status, statusText: res.statusText, response: resText };
|
|
69
|
+
};
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -4,5 +4,6 @@ exports.hashStoreKey = void 0;
|
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
var utils_1 = require("./utils");
|
|
6
6
|
Object.defineProperty(exports, "hashStoreKey", { enumerable: true, get: function () { return utils_1.hashStoreKey; } });
|
|
7
|
+
tslib_1.__exportStar(require("./utils/fetcher"), exports);
|
|
7
8
|
tslib_1.__exportStar(require("./vanilla"), exports);
|
|
8
9
|
tslib_1.__exportStar(require("./react"), exports);
|
|
@@ -34,7 +34,7 @@ const useQueryDefaultDeps = (state) => [
|
|
|
34
34
|
state.isWaitingNextPage,
|
|
35
35
|
state.hasNextPage,
|
|
36
36
|
];
|
|
37
|
-
const
|
|
37
|
+
const fallbackComponent = () => null;
|
|
38
38
|
/**
|
|
39
39
|
* @see https://floppy-disk.vercel.app/docs/api#createquery
|
|
40
40
|
*/
|
|
@@ -411,7 +411,7 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
411
411
|
return state;
|
|
412
412
|
};
|
|
413
413
|
useQuery.Render = (props) => {
|
|
414
|
-
const { queryKey, loading =
|
|
414
|
+
const { queryKey, loading = fallbackComponent, success = fallbackComponent, error = fallbackComponent, } = props;
|
|
415
415
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
416
416
|
const state = useQuery(queryKey);
|
|
417
417
|
if (state.data)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
type FetcherOptions<TResponse = any> = {
|
|
2
|
+
url: string;
|
|
3
|
+
query?: string;
|
|
4
|
+
params?: Record<string, string | number | boolean> | null;
|
|
5
|
+
payload?: any;
|
|
6
|
+
validate?: (response: TResponse) => void | Promise<void>;
|
|
7
|
+
} & RequestInit;
|
|
8
|
+
/**
|
|
9
|
+
* Experimental fetcher - a query/mutation function creator.
|
|
10
|
+
*
|
|
11
|
+
* Can be used for REST or GraphQL.
|
|
12
|
+
*
|
|
13
|
+
* @returns A function to fetch data
|
|
14
|
+
*/
|
|
15
|
+
export declare const fetcher: <TResponse = any, TInput extends any[] = any[]>(options: FetcherOptions<TResponse> | ((...args: TInput) => FetcherOptions<TResponse>)) => (...args: TInput) => Promise<TResponse>;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fetcher = void 0;
|
|
4
|
+
/* eslint-disable no-throw-literal */
|
|
5
|
+
const _1 = require(".");
|
|
6
|
+
const encodeParams = (params) => Object.entries(params)
|
|
7
|
+
.map((kv) => kv.map(encodeURIComponent).join('='))
|
|
8
|
+
.join('&');
|
|
9
|
+
/**
|
|
10
|
+
* Experimental fetcher - a query/mutation function creator.
|
|
11
|
+
*
|
|
12
|
+
* Can be used for REST or GraphQL.
|
|
13
|
+
*
|
|
14
|
+
* @returns A function to fetch data
|
|
15
|
+
*/
|
|
16
|
+
const fetcher = (options) => async (...args) => {
|
|
17
|
+
const { url, query, params, payload, headers, validate, ...rest } = (0, _1.getValueOrComputedValue)(options, ...args);
|
|
18
|
+
let autoOptions = {};
|
|
19
|
+
let searchParams = params;
|
|
20
|
+
if (query) {
|
|
21
|
+
// GraphQL
|
|
22
|
+
autoOptions = {
|
|
23
|
+
method: 'POST',
|
|
24
|
+
body: JSON.stringify({ query, variables: payload || args[0] }),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
else if (rest.method && rest.method.toLowerCase() !== 'get') {
|
|
28
|
+
// REST - Mutation
|
|
29
|
+
autoOptions = {
|
|
30
|
+
body: JSON.stringify(payload === undefined ? args[0] : payload),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
// REST - Query
|
|
35
|
+
if (typeof options === 'object' && params === undefined)
|
|
36
|
+
searchParams = args[0];
|
|
37
|
+
}
|
|
38
|
+
const fetchUrl = searchParams ? [url, encodeParams(searchParams)].join('?') : url;
|
|
39
|
+
const res = await fetch(fetchUrl, {
|
|
40
|
+
headers: { 'Content-Type': 'application/json', ...headers },
|
|
41
|
+
...autoOptions,
|
|
42
|
+
...rest,
|
|
43
|
+
});
|
|
44
|
+
const contentType = res.headers.get('content-type');
|
|
45
|
+
if (contentType && contentType.includes('application/json')) {
|
|
46
|
+
const resJson = await res.json().catch(() => undefined);
|
|
47
|
+
if (resJson !== undefined) {
|
|
48
|
+
if (query && resJson.errors) {
|
|
49
|
+
throw { status: res.status, statusText: res.statusText, response: resJson };
|
|
50
|
+
}
|
|
51
|
+
if (res.ok) {
|
|
52
|
+
if (validate) {
|
|
53
|
+
try {
|
|
54
|
+
await validate(resJson);
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
throw {
|
|
58
|
+
status: res.status,
|
|
59
|
+
statusText: res.statusText,
|
|
60
|
+
response: resJson,
|
|
61
|
+
validationError: err,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return resJson;
|
|
66
|
+
}
|
|
67
|
+
throw { status: res.status, statusText: res.statusText, response: resJson };
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const resText = await res.text().catch(() => undefined);
|
|
71
|
+
throw { status: res.status, statusText: res.statusText, response: resText };
|
|
72
|
+
};
|
|
73
|
+
exports.fetcher = fetcher;
|