Skip to content

Commit

Permalink
refactor(utils): use native fetch
Browse files Browse the repository at this point in the history
  • Loading branch information
unicornware committed Nov 25, 2023
1 parent b93a82c commit b6dfec6
Show file tree
Hide file tree
Showing 10 changed files with 49 additions and 152 deletions.
35 changes: 0 additions & 35 deletions build.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import { defineBuildConfig, type Config } from '@flex-development/mkbuild'
import pathe from '@flex-development/pathe'
import { at } from '@flex-development/tutils'
import type { BuildResult, PluginBuild } from 'esbuild'
import pkg from './package.json' assert { type: 'json' }
import tsconfig from './tsconfig.build.json' assert { type: 'json' }

Expand All @@ -31,40 +30,6 @@ const config: Config = defineBuildConfig({
keepNames: true,
minifySyntax: true,
platform: 'node',
plugins: [
{
name: 'ts-ignore-peers',

/**
* Inserts `// @ts-ignore peer dependency` above property declarations
* using types from peer dependencies.
*
* [1]: https://esbuild.github.io/plugins
*
* @see https://regex101.com/r/6r7Cke
* @see https://github.com/microsoft/TypeScript/issues/38628#issuecomment-1439749496
*
* @param {PluginBuild} build - [esbuild plugin api][1]
* @param {PluginBuild['onEnd']} build.onEnd - Build end callback
* @return {void} Nothing when complete
*/
setup({ onEnd }: PluginBuild): void {
return void onEnd((result: BuildResult<{ write: false }>): void => {
return void (result.outputFiles = result.outputFiles.map(output => {
return output.path.endsWith('.d.mts')
? {
...output,
text: output.text.replace(
/\n( +)(.+?\??: )(\w+<)?(import\('node-fetch'\).+)/g,
'\n$1// @ts-ignore peer dependency\n$1$2$3$4'
)
}
: output
}))
})
}
}
],
target: [
'node' + at(/([\d.]+)/.exec(pkg.engines.node), 0, ''),
tsconfig.compilerOptions.target
Expand Down
2 changes: 1 addition & 1 deletion docs/.vitepress/theme/comments/link-replacements.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"{@linkcode ParsedSubpath}": "/api/interfaces/#parsedsubpath",
"{@linkcode Protocol}": "/api/types#protocol",
"{@linkcode RESOLVE_EXTENSIONS}": "/api/#resolve-extensions",
"{@linkcode RequestInit}": "https://github.com/node-fetch/node-fetch/blob/v3.3.0/@types/index.d.ts#L71-L112",
"{@linkcode RequestInit}": "https://developer.mozilla.org/docs/Web/API/fetch#options",
"{@linkcode RequireStatement}": "/api/interfaces#requirestatement",
"{@linkcode ResolveAliasOptions}": "/api/interfaces#resolvealiasoptions",
"{@linkcode ResolveModuleOptions}": "/api/interfaces#resolvemoduleoptions",
Expand Down
4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,6 @@
"is-ci": "3.0.1",
"jsonc-eslint-parser": "2.4.0",
"lint-staged": "15.1.0",
"node-fetch": "3.3.2",
"node-notifier": "10.0.1",
"prettier": "3.1.0",
"sh-syntax": "0.4.1",
Expand All @@ -168,8 +167,7 @@
"yaml-eslint-parser": "1.2.2"
},
"peerDependencies": {
"@types/node": ">=18.11.9",
"node-fetch": ">=3.3.0"
"@types/node": ">=18.11.9"
},
"peerDependenciesMeta": {
"@types/node": {
Expand Down
1 change: 0 additions & 1 deletion src/interfaces/__tests__/options-get-format.spec-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import type {
Optional,
RequiredKeys
} from '@flex-development/tutils'
import type { RequestInit } from 'node-fetch'
import type TestSubject from '../options-get-format'

describe('unit-d:interfaces/GetFormatOptions', () => {
Expand Down
1 change: 0 additions & 1 deletion src/interfaces/__tests__/options-get-source.spec-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import type {
OrLowercase,
RequiredKeys
} from '@flex-development/tutils'
import type { RequestInit } from 'node-fetch'
import type TestSubject from '../options-get-source'

describe('unit-d:interfaces/GetSourceOptions', () => {
Expand Down
9 changes: 4 additions & 5 deletions src/interfaces/options-get-format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,6 @@ interface GetFormatOptions {
/**
* Enable support for network based modules.
*
* **Note**: Requires [`node-fetch`][1].
*
* [1]: https://github.com/node-fetch/node-fetch
*
* @see https://nodejs.org/docs/latest-v16.x/api/esm.html#https-and-http-imports
*
* @default false
Expand All @@ -49,6 +45,9 @@ interface GetFormatOptions {
/**
* Map file extensions to module formats.
*
* @see {@linkcode Ext}
* @see {@linkcode Format}
*
* @default EXTENSION_FORMAT_MAP
*/
extension_format_map?: Optional<Map<EmptyString | Ext, Format>>
Expand All @@ -74,7 +73,7 @@ interface GetFormatOptions {
*
* @default {}
*/
req?: Optional<import('node-fetch').RequestInit>
req?: Optional<RequestInit>
}

export type { GetFormatOptions as default }
6 changes: 1 addition & 5 deletions src/interfaces/options-get-source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@ interface GetSourceOptions {
/**
* Enable support for network based modules.
*
* **Note**: Requires [`node-fetch`][1].
*
* [1]: https://github.com/node-fetch/node-fetch
*
* @see https://nodejs.org/docs/latest-v16.x/api/esm.html#https-and-http-imports
*
* @default false
Expand Down Expand Up @@ -53,7 +49,7 @@ interface GetSourceOptions {
*
* @default {}
*/
req?: Optional<import('node-fetch').RequestInit>
req?: Optional<RequestInit>
}

export type { GetSourceOptions as default }
85 changes: 40 additions & 45 deletions src/utils/get-format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import { isBuiltin } from '@flex-development/is-builtin'
import pathe, { type Ext } from '@flex-development/pathe'
import {
isEmptyString,
isUndefined,
type EmptyString,
type Nilable,
type Nullable,
Expand Down Expand Up @@ -68,14 +67,7 @@ const getFormat = async (
validateBoolean(wasm_modules, 'options.experimental_wasm_modules')
validateBoolean(ignore_errors, 'options.ignore_errors')
validateMap(extension_format_map, 'options.extension_format_map')
!isUndefined(req) && validateObject(req, 'options.req')

/**
* Module {@linkcode id} as {@linkcode URL}.
*
* @const {URL} url
*/
const url: URL = toURL(id)
validateObject(req, 'options.req')

/**
* Extracts a [MIME type][1] from a {@linkcode URL} href, {@linkcode URL}
Expand All @@ -85,12 +77,12 @@ const getFormat = async (
* [2]: https://developer.mozilla.org/docs/Web/HTTP/Headers/Content-Type
*
* @param {Nullable<string>} value - `URL` component or `content-type` header
* @param {boolean} [content_type=false] - `value` is `content-type` header?
* @param {boolean} [header=false] - `value` is `content-type` header?
* @return {Nilable<Format>} Module format, `null`, or `undefined`
*/
const mimeToFormat = (
value: Nullable<string>,
content_type: boolean = false
header: boolean = false
): Nilable<Format> => {
/**
* Module format for {@linkcode value}.
Expand All @@ -99,39 +91,45 @@ const getFormat = async (
*/
let format: Nilable<Format> = null

// do nothing if value is empty
/* c8 ignore next */ if (!value) return format

// sanitize content-type header
if (content_type) value = value.replace(/;.*/, ',')

// add data: protocol to value
if (!value.startsWith('data:')) value = `data:${value}`

// get format based on mime type
try {
switch (parseDataURL(value).mime) {
case 'application/javascript':
case 'application/typescript':
case 'text/javascript':
format = Format.MODULE
break
case 'application/json':
format = json_modules ? Format.JSON : null
break
case 'application/wasm':
format = wasm_modules ? Format.WASM : null
break
default:
break
if (value) {
// sanitize content-type header
if (header) value = value.replace(/;.*/, ',')

// add data: protocol to value
if (!value.startsWith('data:')) value = `data:${value}`

// get format based on mime type
try {
switch (parseDataURL(value).mime) {
case 'application/javascript':
case 'application/typescript':
case 'text/javascript':
format = Format.MODULE
break
case 'application/json':
format = json_modules ? Format.JSON : null
break
case 'application/wasm':
format = wasm_modules ? Format.WASM : null
break
default:
break
}
} catch {
format = ignore_errors ? undefined : null
}
} catch {
format = ignore_errors ? undefined : null
}

return format
}

/**
* Module {@linkcode id} as {@linkcode URL}.
*
* @const {URL} url
*/
const url: URL = toURL(id)

/**
* Module format for {@linkcode id}.
*
Expand Down Expand Up @@ -198,8 +196,6 @@ const getFormat = async (
// esm-only and module id does not include file extension
if (scope && scope.pkgjson.type === Format.MODULE) {
if (isEmptyString(ext)) {
const { pkg } = scope

/**
* Basename of {@linkcode url.pathname}
*
Expand All @@ -208,16 +204,16 @@ const getFormat = async (
const basename: string = pathe.basename(url.pathname)

/**
* Relative path from {@linkcode pkg} to {@linkcode url.pathname}.
* Relative path from `package.json` file to module id.
*
* @const {string} relative
*/
const relative: string = pathe
.relative(pkg, url.pathname)
.relative(scope.pkg, url.pathname)
.slice(1)

suggestion =
`Loading extensionless files is not supported inside of "type":"module" package.json contexts. The package.json file ${pkg} caused this "type":"module" context. Try changing ${url.pathname} to have a file extension. Note the "bin" field of package.json can point to a file with an extension, for example {"type":"module","bin":{"${basename}":"${relative}.js"}}`
`Loading extensionless files is not supported inside of "type":"module" package.json contexts. The package.json file ${scope.pkg} caused this "type":"module" context. Try changing ${url.pathname} to have a file extension. Note the "bin" field of package.json can point to a file with an extension, for example {"type":"module","bin":{"${basename}":"${relative}.js"}}`
}
}

Expand All @@ -228,8 +224,7 @@ const getFormat = async (
case 'http:':
case 'https:':
if (network_imports) {
const { default: fetch } = await import('node-fetch')
const { headers } = await fetch(url.href, req)
const { headers } = await fetch(url, req)
format = mimeToFormat(headers.get('content-type'), true)
} else {
format = ignore_errors ? undefined : null
Expand Down
5 changes: 2 additions & 3 deletions src/utils/get-source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ const getSource = async (
validateBoolean(network_imports, 'options.experimental_network_imports')
!isUndefined(format) && validateString(format, 'options.format')
validateBoolean(ignore_errors, 'options.ignore_errors')
!isUndefined(req) && validateObject(req, 'options.req')
validateObject(req, 'options.req')

// exit early if format is Format.BUILTIN
if (format === Format.BUILTIN) return undefined
Expand Down Expand Up @@ -105,8 +105,7 @@ const getSource = async (
case 'http:':
case 'https:':
if (network_imports) {
const { default: fetch } = await import('node-fetch')
source = await (await fetch(url.href, req)).text()
source = await (await fetch(url, req)).text()
} else {
err = true
}
Expand Down
Loading

0 comments on commit b6dfec6

Please sign in to comment.