๐Ÿ“ฆ kitten / fetch-nodeshim

๐Ÿ“„ webstd.ts ยท 82 lines
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/// <reference types="@types/node" />

import * as buffer from 'node:buffer';

type Or<T, U> = void extends T ? U : T;

export type BodyInit =
  | ArrayBuffer
  | AsyncIterable<Uint8Array>
  | Blob
  | FormData
  | Iterable<Uint8Array>
  | NodeJS.ArrayBufferView
  | URLSearchParams
  | null
  | string;

// See: https://nodejs.org/docs/latest-v20.x/api/globals.html#class-file
// The `File` global was only added in Node.js 20
interface _File extends Or<File, globalThis.File> {}
const _File: Or<typeof File, typeof buffer.File> = buffer.File;
if (typeof globalThis.File === 'undefined') {
  globalThis.File = _File;
}

declare global {
  var File: typeof _File;

  // NOTE: In case undici was used, but its types aren't applied, this needs to be added
  interface RequestInit {
    duplex?: 'half';
  }
}

// There be dragons here.
// This is complex because of overlapping definitions in lib.dom, @types/node, and undici-types
// Some types define and overload constructor interfaces with type interfaces
// Here, we have to account for global differences and split the overloads apart

interface _RequestInit extends Or<RequestInit, globalThis.RequestInit> {}
interface _ResponseInit extends Or<ResponseInit, globalThis.ResponseInit> {}

interface _URLSearchParams
  extends Or<URLSearchParams, globalThis.URLSearchParams> {}
interface URLSearchParamsClass
  extends Or<typeof URLSearchParams, typeof globalThis.URLSearchParams> {}
const _URLSearchParams: URLSearchParamsClass = URLSearchParams as any;

interface _URL extends Or<URL, globalThis.URL> {}
interface URLClass extends Or<typeof URL, typeof globalThis.URL> {}
const _URL: URLClass = URL;

interface _Request extends Or<Request, globalThis.Request> {}
interface RequestClass extends Or<typeof Request, typeof globalThis.Request> {}
const _Request: RequestClass = Request;

interface _Response extends Or<Response, globalThis.Response> {}
interface ResponseClass
  extends Or<typeof Response, typeof globalThis.Response> {}
const _Response: ResponseClass = Response;

interface _Headers extends Or<Headers, globalThis.Headers> {}
interface HeadersClass extends Or<typeof Headers, typeof globalThis.Headers> {}
const _Headers: HeadersClass = Headers;

interface _FormData extends Or<FormData, globalThis.FormData> {}
interface FormDataClass
  extends Or<typeof FormData, typeof globalThis.FormData> {}
const _FormData: FormDataClass = FormData;

export {
  type _RequestInit as RequestInit,
  type _ResponseInit as ResponseInit,
  _File as File,
  _URL as URL,
  _URLSearchParams as URLSearchParams,
  _Request as Request,
  _Response as Response,
  _Headers as Headers,
  _FormData as FormData,
};