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 CHANGED
@@ -1,3 +1,4 @@
1
1
  export { hashStoreKey } from './utils';
2
+ export * from './utils/fetcher';
2
3
  export * from './vanilla';
3
4
  export * from './react';
package/esm/index.js CHANGED
@@ -1,3 +1,4 @@
1
1
  export { hashStoreKey } from './utils';
2
+ export * from './utils/fetcher';
2
3
  export * from './vanilla';
3
4
  export * from './react';
@@ -31,7 +31,7 @@ const useQueryDefaultDeps = (state) => [
31
31
  state.isWaitingNextPage,
32
32
  state.hasNextPage,
33
33
  ];
34
- const defaultElement = () => null;
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 = defaultElement, success = defaultElement, error = defaultElement, } = props;
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
@@ -1,3 +1,4 @@
1
1
  export { hashStoreKey } from './utils';
2
+ export * from './utils/fetcher';
2
3
  export * from './vanilla';
3
4
  export * from './react';
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 defaultElement = () => null;
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 = defaultElement, success = defaultElement, error = defaultElement, } = props;
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "floppy-disk",
3
- "version": "2.9.0-beta.2",
3
+ "version": "2.10.0-beta.1",
4
4
  "description": "FloppyDisk - lightweight, simple, and powerful state management library",
5
5
  "keywords": [
6
6
  "state",