UNPKG

solid-use

Version:
8 lines (7 loc) 8.44 kB
{ "version": 3, "sources": ["../../../src/fetch.ts"], "sourcesContent": ["import type { Resource } from 'solid-js';\nimport { createEffect, createResource, createSignal } from 'solid-js';\n\nconst nativeFetch = globalThis.fetch;\n\ntype Signalify<T> = T | (() => T);\n\nfunction isSignal<T>(value: Signalify<T>): value is () => T {\n return typeof value === 'function';\n}\n\nfunction fromSignal<T>(value: Signalify<T>): T {\n if (isSignal(value)) {\n return value();\n }\n return value;\n}\n\ntype FetchParameters = [RequestInfo | URL, RequestInit | undefined];\n\nexport class SuspensefulFetchResponse {\n private input: Signalify<RequestInfo | URL>;\n\n private init?: Signalify<RequestInit | undefined>;\n\n constructor(\n input: Signalify<RequestInfo | URL>,\n init?: Signalify<RequestInit | undefined>,\n ) {\n this.input = input;\n this.init = init;\n }\n\n private readResponse(): FetchParameters {\n return [fromSignal(this.input), fromSignal(this.init)];\n }\n\n arrayBuffer(): Resource<ArrayBuffer | undefined> {\n return createResource(\n () => this.readResponse(),\n async ([localInput, localInit]) => {\n const response = await nativeFetch(localInput, localInit);\n return response.arrayBuffer();\n },\n )[0];\n }\n\n blob(): Resource<Blob | undefined> {\n return createResource(\n () => this.readResponse(),\n async ([localInput, localInit]) => {\n const response = await nativeFetch(localInput, localInit);\n return response.blob();\n },\n )[0];\n }\n\n formData(): Resource<FormData | undefined> {\n return createResource(\n () => this.readResponse(),\n async ([localInput, localInit]) => {\n const response = await nativeFetch(localInput, localInit);\n return response.formData();\n },\n )[0];\n }\n\n json<T>(): Resource<T> {\n return createResource(\n () => this.readResponse(),\n async ([localInput, localInit]) => {\n const response = await nativeFetch(localInput, localInit);\n return response.json();\n },\n )[0];\n }\n\n text(): Resource<string | undefined> {\n return createResource(\n () => this.readResponse(),\n async ([localInput, localInit]) => {\n const response = await nativeFetch(localInput, localInit);\n return response.text();\n },\n )[0];\n }\n}\n\nexport interface FetchPending<T> {\n status: 'pending';\n value?: Promise<T>;\n}\n\nexport interface FetchSuccess<T> {\n status: 'success';\n value: T;\n}\n\nexport interface FetchFailure {\n status: 'failure';\n value: any;\n}\n\nexport type FetchResult<T> = FetchPending<T> | FetchSuccess<T> | FetchFailure;\n\nclass InternalFetchResult<T> {\n private source: () => FetchResult<T>;\n\n constructor(source: () => FetchResult<T>) {\n this.source = source;\n }\n\n get value(): FetchResult<T>['value'] {\n return this.source().value;\n }\n\n get status(): FetchResult<T>['status'] {\n return this.source().status;\n }\n}\n\nfunction useAsync<T>(source: () => Promise<T>): FetchResult<T> {\n const [value, setValue] = createSignal<FetchResult<T>>({\n status: 'pending',\n });\n\n createEffect(() => {\n const result = source();\n\n setValue({\n status: 'pending',\n value: result,\n });\n\n result.then(\n val => {\n setValue({\n status: 'success',\n value: val,\n });\n },\n val => {\n setValue({\n status: 'failure',\n value: val,\n });\n },\n );\n });\n\n return new InternalFetchResult(value);\n}\n\nexport class SuspenselessFetchResponse {\n private input: Signalify<RequestInfo | URL>;\n\n private init?: Signalify<RequestInit | undefined>;\n\n constructor(\n input: Signalify<RequestInfo | URL>,\n init?: Signalify<RequestInit | undefined>,\n ) {\n this.input = input;\n this.init = init;\n }\n\n private async readResponse() {\n return await nativeFetch(fromSignal(this.input), fromSignal(this.init));\n }\n\n arrayBuffer(): FetchResult<ArrayBuffer> {\n return useAsync(async () => {\n const response = await this.readResponse();\n return response.arrayBuffer();\n });\n }\n\n blob(): FetchResult<Blob> {\n return useAsync(async () => {\n const response = await this.readResponse();\n return response.blob();\n });\n }\n\n formData(): FetchResult<FormData> {\n return useAsync(async () => {\n const response = await this.readResponse();\n return response.formData();\n });\n }\n\n json<T>(): FetchResult<T> {\n return useAsync(async () => {\n const response = await this.readResponse();\n return response.json();\n });\n }\n\n text(): FetchResult<string> {\n return useAsync(async () => {\n const response = await this.readResponse();\n return response.text();\n });\n }\n}\n\nfunction fetch(\n input: Signalify<RequestInfo | URL>,\n init?: Signalify<RequestInit | undefined>,\n suspense?: false,\n): SuspenselessFetchResponse;\nfunction fetch(\n input: Signalify<RequestInfo | URL>,\n init?: Signalify<RequestInit | undefined>,\n suspense?: true,\n): SuspensefulFetchResponse;\nfunction fetch(\n input: Signalify<RequestInfo | URL>,\n init?: Signalify<RequestInit | undefined>,\n suspense?: boolean,\n): SuspenselessFetchResponse | SuspensefulFetchResponse {\n if (suspense) {\n return new SuspensefulFetchResponse(input, init);\n }\n return new SuspenselessFetchResponse(input, init);\n}\n\nexport default fetch;\n"], "mappings": "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", "names": [] }