* Create a custom module loader for @deno/doc. * * Fetches modules from URLs using fetch(), with proper timeout handling.
()
| 71 | * Fetches modules from URLs using fetch(), with proper timeout handling. |
| 72 | */ |
| 73 | function createLoader(): ( |
| 74 | specifier: string, |
| 75 | isDynamic?: boolean, |
| 76 | cacheSetting?: string, |
| 77 | checksum?: string, |
| 78 | ) => Promise<LoadResponse | undefined> { |
| 79 | return async ( |
| 80 | specifier: string, |
| 81 | _isDynamic?: boolean, |
| 82 | _cacheSetting?: string, |
| 83 | _checksum?: string, |
| 84 | ) => { |
| 85 | const url = URL.parse(specifier) |
| 86 | |
| 87 | if (url === null) { |
| 88 | return undefined |
| 89 | } |
| 90 | |
| 91 | // Only handle http/https URLs |
| 92 | if (url.protocol !== 'http:' && url.protocol !== 'https:') { |
| 93 | return undefined |
| 94 | } |
| 95 | |
| 96 | try { |
| 97 | const response = await $fetch.raw<Blob>(url.toString(), { |
| 98 | method: 'GET', |
| 99 | timeout: FETCH_TIMEOUT_MS, |
| 100 | redirect: 'follow', |
| 101 | }) |
| 102 | |
| 103 | if (response.status !== 200) { |
| 104 | return undefined |
| 105 | } |
| 106 | |
| 107 | const content = (await response._data?.text()) ?? '' |
| 108 | const headers: Record<string, string> = {} |
| 109 | for (const [key, value] of response.headers) { |
| 110 | headers[key.toLowerCase()] = value |
| 111 | } |
| 112 | |
| 113 | return { |
| 114 | kind: 'module', |
| 115 | specifier: response.url || specifier, |
| 116 | headers, |
| 117 | content, |
| 118 | } |
| 119 | } catch (e) { |
| 120 | // eslint-disable-next-line no-console |
| 121 | console.error(e) |
| 122 | return undefined |
| 123 | } |
| 124 | } |
| 125 | } |
| 126 | |
| 127 | /** |
| 128 | * Create a module resolver for @deno/doc. |