aboutsummaryrefslogtreecommitdiff
path: root/packages/webapi/src/lib/fetch.ts
blob: b099e44af310fa0495f0663e32ed8fa8d1b7c0c0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import type { RequestInit } from 'node-fetch'
import { default as nodeFetch, Headers, Request, Response } from 'node-fetch'
import Stream from 'node:stream'
import * as _ from './utils'

export { Headers, Request, Response }

export const fetch = {
	fetch(
		resource: string | Request,
		init?: Partial<FetchInit>
	): Promise<Response> {
		const resourceURL = new URL(
			_.__object_isPrototypeOf(Request.prototype, resource)
				? (resource as Request).url
				: _.pathToPosix(resource),
			typeof Object(globalThis.process).cwd === 'function'
				? 'file:' + _.pathToPosix(process.cwd()) + '/'
				: 'file:'
		)

		if (resourceURL.protocol.toLowerCase() === 'file:') {
			return import('node:fs').then((fs) => {
				try {
					const stats = fs.statSync(resourceURL)
					const body = fs.createReadStream(resourceURL)

					return new Response(body, {
						status: 200,
						statusText: '',
						headers: {
							'content-length': String(stats.size),
							date: new Date().toUTCString(),
							'last-modified': new Date(stats.mtimeMs).toUTCString(),
						},
					})
				} catch (error) {
					const body = new Stream.Readable()

					body._read = () => {}
					body.push(null)

					return new Response(body, {
						status: 404,
						statusText: '',
						headers: {
							date: new Date().toUTCString(),
						},
					})
				}
			})
		} else {
			return nodeFetch(resource, init)
		}
	},
}.fetch

type USVString = {} & string

interface FetchInit {
	body: RequestInit['body']
	cache:
		| 'default'
		| 'no-store'
		| 'reload'
		| 'no-cache'
		| 'force-cache'
		| 'only-if-cached'
	credentials: 'omit' | 'same-origin' | 'include'
	headers: Headers | Record<string, string>
	method:
		| 'GET'
		| 'HEAD'
		| 'POST'
		| 'PUT'
		| 'DELETE'
		| 'CONNECT'
		| 'OPTIONS'
		| 'TRACE'
		| 'PATCH'
		| USVString
	mode: 'cors' | 'no-cors' | 'same-origin' | USVString
	redirect: 'follow' | 'manual' | 'error'
	referrer: USVString
	referrerPolicy:
		| 'no-referrer'
		| 'no-referrer-when-downgrade'
		| 'same-origin'
		| 'origin'
		| 'strict-origin'
		| 'origin-when-cross-origin'
		| 'strict-origin-when-cross-origin'
		| 'unsafe-url'
	integrity: USVString
	keepalive: boolean
	signal: AbortSignal
}