Created
December 27, 2022 20:42
-
-
Save mahdiboomeri/a44661d62ba96f8306005eb303115533 to your computer and use it in GitHub Desktop.
Revisions
-
mahdiboomeri created this gist
Dec 27, 2022 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,96 @@ import type { FetchError } from "ofetch"; import type { NitroFetchRequest } from "nitropack"; import type { FetchResult, UseFetchOptions, AsyncData } from "#app"; import type { KeyOfRes, PickFrom, _AsyncData, } from "#app/composables/asyncData"; import type { Ref } from "vue"; /** * @see https://github.com/remix-run/remix/blob/2248669ed59fd716e267ea41df5d665d4781f4a9/packages/remix-server-runtime/serialize.ts */ type JsonPrimitive = | string | number | boolean | String | Number | Boolean | null; type NonJsonPrimitive = undefined | Function | symbol; /* * `any` is the only type that can let you equate `0` with `1` * See https://stackoverflow.com/a/49928360/1490091 */ type IsAny<T> = 0 extends 1 & T ? true : false; // prettier-ignore type Serialize<T> = IsAny<T> extends true ? any : T extends JsonPrimitive ? T : T extends Map<any,any> | Set<any> ? {} : T extends NonJsonPrimitive ? never : T extends { toJSON(): infer U } ? U : T extends [] ? [] : T extends [unknown, ...unknown[]] ? SerializeTuple<T> : T extends ReadonlyArray<infer U> ? (U extends NonJsonPrimitive ? null : Serialize<U>)[] : T extends object ? SerializeObject<UndefinedToOptional<T>> : never; /** JSON serialize [tuples](https://www.typescriptlang.org/docs/handbook/2/objects.html#tuple-types) */ type SerializeTuple<T extends [unknown, ...unknown[]]> = { [k in keyof T]: T[k] extends NonJsonPrimitive ? null : Serialize<T[k]>; }; /** JSON serialize objects (not including arrays) and classes */ type SerializeObject<T extends object> = { [k in keyof T]: T[k] extends NonJsonPrimitive ? never : Serialize<T[k]>; }; /* * For an object T, if it has any properties that are a union with `undefined`, * make those into optional properties instead. * * Example: { a: string | undefined} --> { a?: string} */ type FilterDefinedKeys<TObj extends object> = { [TKey in keyof TObj]: undefined extends TObj[TKey] ? never : TKey; }[keyof TObj]; type UndefinedToOptional<T extends object> = { // Property is not a union with `undefined`, keep as-is [k in keyof Pick<T, FilterDefinedKeys<T>>]: T[k]; } & { // Property _is_ a union with `defined`. Set as optional (via `?`) and remove `undefined` from the union [k in keyof Omit<T, FilterDefinedKeys<T>>]?: Exclude<T[k], undefined>; }; interface _NonNullableAsyncData<Data, Error> extends _AsyncData<Data, Error> { data: Ref<Data>; } type NonNullableAsyncData<Data, Error> = _NonNullableAsyncData<Data, Error> & Promise<_NonNullableAsyncData<Data, Error>>; export const useSerializableFetch = < ResT = void, ErrorT = FetchError, ReqT extends NitroFetchRequest = NitroFetchRequest, _ResT = ResT extends void ? FetchResult<ReqT> : ResT, Transform extends (res: _ResT) => any = (res: _ResT) => _ResT, PickKeys extends KeyOfRes<Transform> = KeyOfRes<Transform> >( request: Ref<ReqT> | ReqT | (() => ReqT), opts?: UseFetchOptions<_ResT, Transform, PickKeys> ) => { return useFetch<ResT, ErrorT, ReqT, _ResT, Transform, PickKeys>( request, opts ) as NonNullableAsyncData< PickFrom<Serialize<ReturnType<Transform>>, PickKeys>, ErrorT | null >; };