| 1 | /** |
| 2 | * functions to load Node.js apis via `globalThis.process`. trivially bundlable |
| 3 | * for the browser. does not depend on `@types/node` and does not intend to |
| 4 | * define types for the entire api. instead, this file's types are used for |
| 5 | * other library modules like `lib/log.ts` to bind to the system. |
| 6 | * |
| 7 | * if you are using a competent bundler, you can define `globalThis.process` as |
| 8 | * a bundling constant (esbuild: `--define`) to enable tree shaking across the |
| 9 | * library to only include browser code paths. |
| 10 | * |
| 11 | * @module |
| 12 | */ |
| 13 | |
| 14 | export const process: Process | undefined = (globalThis as { process?: Process }).process |
| 15 | && (globalThis as { process?: Process }).process?.versions?.node |
| 16 | ? (globalThis as { process?: Process }).process |
| 17 | : undefined; |
| 18 | |
| 19 | export const isServer: boolean = !!process; |
| 20 | |
| 21 | /** partial types for Node.js `globalThis.process` */ |
| 22 | interface Process { |
| 23 | getBuiltinModule<K extends keyof Builtins>(name: K): Builtins[K] | null; |
| 24 | binding?<K extends keyof Bindings>(name: K): Bindings[K] | null; |
| 25 | addListener(event: string, callback: () => void): this; |
| 26 | versions: { node?: string; bun?: string; deno?: string }; |
| 27 | stdout: Tty; |
| 28 | stderr: Tty; |
| 29 | } |
| 30 | |
| 31 | interface Tty { |
| 32 | isTTY: boolean; |
| 33 | /** only present when the stream is a tty */ |
| 34 | columns: number | undefined; |
| 35 | /** only present when the stream is a tty */ |
| 36 | rows: number | undefined; |
| 37 | addListener(event: string, callback: () => void): this; |
| 38 | removeListener(event: string, callback: () => void): this; |
| 39 | end(text?: string | Uint8Array): this; |
| 40 | write(text: string | Uint8Array): boolean; |
| 41 | } |
| 42 | |
| 43 | /** |
| 44 | * Subset of Node.js builtin types needed to not depend on the problematic |
| 45 | * "@types/node" package. |
| 46 | */ |
| 47 | interface Builtins { |
| 48 | "fs": { |
| 49 | existsSync(file: string): boolean; |
| 50 | readFileSync(file: string, encoding: "utf-8"): string; |
| 51 | readFileSync(file: string): Uint8Array; |
| 52 | }; |
| 53 | "path": { |
| 54 | isAbsolute(file: string): boolean; |
| 55 | dirname(file: string): string; |
| 56 | basename(file: string): string; |
| 57 | join(...parts: string[]): string; |
| 58 | sep: string; |
| 59 | }; |
| 60 | "util": { |
| 61 | inspect(object: unknown): string; |
| 62 | formatWithOptions( |
| 63 | options: { colors?: boolean }, |
| 64 | ...args: unknown[] |
| 65 | ): string; |
| 66 | }; |
| 67 | "stream": { |
| 68 | Readable: { |
| 69 | toWeb(nodeStream: unknown): ReadableStream; |
| 70 | fromWeb(webStream: ReadableStream): { pipe: (other: unknown) => void }; |
| 71 | }; |
| 72 | Writable: { |
| 73 | prototype: { |
| 74 | write: (value: string) => boolean; |
| 75 | }; |
| 76 | }; |
| 77 | }; |
| 78 | } |
| 79 | |
| 80 | /** subset of Node.js binding types */ |
| 81 | interface Bindings { |
| 82 | /** |
| 83 | * key value mapping of internal module id to its source code. |
| 84 | * ``` |
| 85 | * { "fs": "// Copyright Joyent, Inc. and other Node contributors.\n... |
| 86 | * ``` |
| 87 | */ |
| 88 | "natives": Partial<Record<string, string>>; |
| 89 | } |
| 90 | |
| 91 | /** return a built-in module */ |
| 92 | export function builtin<K extends keyof Builtins>( |
| 93 | name: K, |
| 94 | ): Builtins[K] | undefined { |
| 95 | return process?.getBuiltinModule(name) ?? undefined; |
| 96 | } |
| 97 | |
| 98 | /** return a built-in semi-private binding */ |
| 99 | export function binding<K extends keyof Bindings>( |
| 100 | name: K, |
| 101 | ): Bindings[K] | undefined { |
| 102 | if (!process) return undefined; |
| 103 | try { |
| 104 | return process.binding?.(name) ?? undefined; |
| 105 | } catch { |
| 106 | return undefined; |
| 107 | } |
| 108 | } |
| 109 | |
| 110 | /** copy of `keyof typeof import('node:os').constants.errno` */ |
| 111 | // deno-fmt-ignore-next |
| 112 | export type ErrorCode = |
| 113 | | (string & {}) |
| 114 | | "E2BIG" |
| 115 | | "EACCES" |
| 116 | | "EADDRINUSE" |
| 117 | | "EADDRNOTAVAIL" |
| 118 | | "EAFNOSUPPORT" |
| 119 | | "EAGAIN" |
| 120 | | "EALREADY" |
| 121 | | "EBADF" |
| 122 | | "EBADMSG" |
| 123 | | "EBUSY" |
| 124 | | "ECANCELED" |
| 125 | | "ECHILD" |
| 126 | | "ECONNABORTED" |
| 127 | | "ECONNREFUSED" |
| 128 | | "ECONNRESET" |
| 129 | | "EDEADLK" |
| 130 | | "EDESTADDRREQ" |
| 131 | | "EDOM" |
| 132 | | "EDQUOT" |
| 133 | | "EEXIST" |
| 134 | | "EFAULT" |
| 135 | | "EFBIG" |
| 136 | | "EHOSTUNREACH" |
| 137 | | "EIDRM" |
| 138 | | "EILSEQ" |
| 139 | | "EINPROGRESS" |
| 140 | | "EINTR" |
| 141 | | "EINVAL" |
| 142 | | "EIO" |
| 143 | | "EISCONN" |
| 144 | | "EISDIR" |
| 145 | | "ELOOP" |
| 146 | | "EMFILE" |
| 147 | | "EMLINK" |
| 148 | | "EMSGSIZE" |
| 149 | | "EMULTIHOP" |
| 150 | | "ENAMETOOLONG" |
| 151 | | "ENETDOWN" |
| 152 | | "ENETRESET" |
| 153 | | "ENETUNREACH" |
| 154 | | "ENFILE" |
| 155 | | "ENOBUFS" |
| 156 | | "ENODATA" |
| 157 | | "ENODEV" |
| 158 | | "ENOENT" |
| 159 | | "ENOEXEC" |
| 160 | | "ENOLCK" |
| 161 | | "ENOLINK" |
| 162 | | "ENOMEM" |
| 163 | | "ENOMSG" |
| 164 | | "ENOPROTOOPT" |
| 165 | | "ENOSPC" |
| 166 | | "ENOSR" |
| 167 | | "ENOSTR" |
| 168 | | "ENOSYS" |
| 169 | | "ENOTCONN" |
| 170 | | "ENOTDIR" |
| 171 | | "ENOTEMPTY" |
| 172 | | "ENOTSOCK" |
| 173 | | "ENOTSUP" |
| 174 | | "ENOTTY" |
| 175 | | "ENXIO" |
| 176 | | "EOPNOTSUPP" |
| 177 | | "EOVERFLOW" |
| 178 | | "EPERM" |
| 179 | | "EPIPE" |
| 180 | | "EPROTO" |
| 181 | | "EPROTONOSUPPORT" |
| 182 | | "EPROTOTYPE" |
| 183 | | "ERANGE" |
| 184 | | "EROFS" |
| 185 | | "ESPIPE" |
| 186 | | "ESRCH" |
| 187 | | "ESTALE" |
| 188 | | "ETIME" |
| 189 | | "ETIMEDOUT" |
| 190 | | "ETXTBSY" |
| 191 | | "EWOULDBLOCK" |
| 192 | | "EXDEV" |
| 193 | | "WSAEINTR" |
| 194 | | "WSAEBADF" |
| 195 | | "WSAEACCES" |
| 196 | | "WSAEFAULT" |
| 197 | | "WSAEINVAL" |
| 198 | | "WSAEMFILE" |
| 199 | | "WSAEWOULDBLOCK" |
| 200 | | "WSAEINPROGRESS" |
| 201 | | "WSAEALREADY" |
| 202 | | "WSAENOTSOCK" |
| 203 | | "WSAEDESTADDRREQ" |
| 204 | | "WSAEMSGSIZE" |
| 205 | | "WSAEPROTOTYPE" |
| 206 | | "WSAENOPROTOOPT" |
| 207 | | "WSAEPROTONOSUPPORT" |
| 208 | | "WSAESOCKTNOSUPPORT" |
| 209 | | "WSAEOPNOTSUPP" |
| 210 | | "WSAEPFNOSUPPORT" |
| 211 | | "WSAEAFNOSUPPORT" |
| 212 | | "WSAEADDRINUSE" |
| 213 | | "WSAEADDRNOTAVAIL" |
| 214 | | "WSAENETDOWN" |
| 215 | | "WSAENETUNREACH" |
| 216 | | "WSAENETRESET" |
| 217 | | "WSAECONNABORTED" |
| 218 | | "WSAECONNRESET" |
| 219 | | "WSAENOBUFS" |
| 220 | | "WSAEISCONN" |
| 221 | | "WSAENOTCONN" |
| 222 | | "WSAESHUTDOWN" |
| 223 | | "WSAETOOMANYREFS" |
| 224 | | "WSAETIMEDOUT" |
| 225 | | "WSAECONNREFUSED" |
| 226 | | "WSAELOOP" |
| 227 | | "WSAENAMETOOLONG" |
| 228 | | "WSAEHOSTDOWN" |
| 229 | | "WSAEHOSTUNREACH" |
| 230 | | "WSAENOTEMPTY" |
| 231 | | "WSAEPROCLIM" |
| 232 | | "WSAEUSERS" |
| 233 | | "WSAEDQUOT" |
| 234 | | "WSAESTALE" |
| 235 | | "WSAEREMOTE" |
| 236 | | "WSASYSNOTREADY" |
| 237 | | "WSAVERNOTSUPPORTED" |
| 238 | | "WSANOTINITIALISED" |
| 239 | | "WSAEDISCON" |
| 240 | | "WSAENOMORE" |
| 241 | | "WSAECANCELLED" |
| 242 | | "WSAEINVALIDPROCTABLE" |
| 243 | | "WSAEINVALIDPROVIDER" |
| 244 | | "WSAEPROVIDERFAILEDINIT" |
| 245 | | "WSASYSCALLFAILURE" |
| 246 | | "WSASERVICE_NOT_FOUND" |
| 247 | | "WSATYPE_NOT_FOUND" |
| 248 | | "WSA_E_NO_MORE" |
| 249 | | "WSA_E_CANCELLED" |
| 250 | | "WSAEREFUSED"; |