Skip to content

Commit ae7b2ec

Browse files
committed
feat(lib): toUrl
Signed-off-by: Lexus Drumgold <unicornware@flexdevelopment.llc>
1 parent 711d283 commit ae7b2ec

File tree

9 files changed

+80
-22
lines changed

9 files changed

+80
-22
lines changed

README.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ import {
9292
resolveModule,
9393
resolver,
9494
root,
95-
toRelativeSpecifier
95+
toRelativeSpecifier,
96+
toUrl
9697
} from '@flex-development/mlly'
9798
```
9899

@@ -132,6 +133,7 @@ This package exports the following identifiers:
132133
- `packageTargetResolve`
133134
- [`root`](./src/lib/root.mts)
134135
- [`toRelativeSpecifier`](./src/lib/to-relative-specifier.mts)
136+
- [`toUrl`](./src/lib/to-url.mts)
135137

136138
There is no default export.
137139

src/__snapshots__/index.e2e.snap

+1
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,6 @@ exports[`e2e:mlly > should expose public api 1`] = `
3434
"resolver",
3535
"root",
3636
"toRelativeSpecifier",
37+
"toUrl",
3738
]
3839
`;

src/lib/__snapshots__/to-url.snap

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2+
3+
exports[`unit:lib/toUrl > should return \`id\` as \`URL\` (0) 1`] = `"node:os"`;
4+
5+
exports[`unit:lib/toUrl > should return \`id\` as \`URL\` (1) 1`] = `file://\${process.cwd()}/path`;
6+
7+
exports[`unit:lib/toUrl > should return \`id\` as \`URL\` (2) 1`] = `file://\${process.cwd()}/src/lib/__tests__/to-url.spec.mts`;
8+
9+
exports[`unit:lib/toUrl > should return \`id\` as \`URL\` (3) 1`] = `"node:test"`;
10+
11+
exports[`unit:lib/toUrl > should return \`id\` as \`URL\` (4) 1`] = `file://\${process.cwd()}/tsconfig.build.json`;

src/lib/__tests__/to-url.spec.mts

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
* @file Unit Tests - toUrl
3+
* @module mlly/lib/tests/unit/toUrl
4+
*/
5+
6+
import cwd from '#lib/cwd'
7+
import testSubject from '#lib/to-url'
8+
import pathe from '@flex-development/pathe'
9+
10+
describe('unit:lib/toUrl', () => {
11+
it.each<Parameters<typeof testSubject>>([
12+
['os'],
13+
['path', cwd()],
14+
[import.meta.url],
15+
[new URL('node:test')],
16+
[pathe.resolve('tsconfig.build.json')]
17+
])('should return `id` as `URL` (%#)', (id, parent) => {
18+
expect(testSubject(id, parent)).toMatchSnapshot()
19+
})
20+
})

src/lib/get-source.mts

+2-15
Original file line numberDiff line numberDiff line change
@@ -5,35 +5,26 @@
55

66
import fs from '#internal/fs'
77
import process from '#internal/process'
8-
import canParseUrl from '#lib/can-parse-url'
98
import isFile from '#lib/is-file'
9+
import toUrl from '#lib/to-url'
1010
import {
1111
ERR_UNSUPPORTED_ESM_URL_SCHEME,
1212
type ErrUnsupportedEsmUrlScheme
1313
} from '@flex-development/errnode'
14-
import { isBuiltin } from '@flex-development/is-builtin'
1514
import type {
1615
GetSourceContext,
1716
GetSourceHandler,
1817
GetSourceOptions,
1918
ModuleId,
2019
Protocol
2120
} from '@flex-development/mlly'
22-
import pathe from '@flex-development/pathe'
2321
import { ok } from 'devlop'
2422

2523
export default getSource
2624

2725
/**
2826
* Get the source code for `id`.
2927
*
30-
* > 👉 **Note**: If `id` is not a [builtin module][builtin-module] and also
31-
* > cannot be parsed as an {@linkcode URL}, it will be assumed to be a path and
32-
* > converted to a [`file:` URL][file-url].
33-
*
34-
* [builtin-module]: https://nodejs.org/api/esm.html#builtin-modules
35-
* [file-url]: https://nodejs.org/api/esm.html#file-urls
36-
*
3728
* @see {@linkcode ErrUnsupportedEsmUrlScheme}
3829
* @see {@linkcode GetSourceOptions}
3930
* @see {@linkcode ModuleId}
@@ -85,11 +76,7 @@ async function getSource(
8576
*
8677
* @const {URL} url
8778
*/
88-
const url: URL = isBuiltin(id)
89-
? new URL('node:' + String(id).replace(/^node:/, ''))
90-
: canParseUrl(id)
91-
? new URL(id)
92-
: (ok(typeof id === 'string', 'expected string'), pathe.pathToFileURL(id))
79+
const url: URL = toUrl(id)
9380

9481
/**
9582
* Source code handler for {@linkcode url}.

src/lib/index.mts

+1
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,4 @@ export * from '#lib/resolver'
3838
export * as resolver from '#lib/resolver'
3939
export { default as root } from '#lib/root'
4040
export { default as toRelativeSpecifier } from '#lib/to-relative-specifier'
41+
export { default as toUrl } from '#lib/to-url'

src/lib/resolver.mts

+2-3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import lookupPackageScope from '#lib/lookup-package-scope'
2020
import patternMatch from '#lib/pattern-match'
2121
import readPackageJson from '#lib/read-package-json'
2222
import root from '#lib/root'
23+
import toUrl from '#lib/to-url'
2324
import {
2425
codes,
2526
ERR_INVALID_MODULE_SPECIFIER,
@@ -672,9 +673,7 @@ async function packageResolve(
672673
mainFields?: MainField[] | Set<MainField> | null | undefined,
673674
fs?: FileSystem | null | undefined
674675
): Promise<URL> {
675-
if (isBuiltin(specifier)) {
676-
return new URL('node:' + specifier.replace(/^node:/, ''))
677-
}
676+
if (isBuiltin(specifier)) return toUrl(specifier)
678677

679678
/**
680679
* Index of separator in {@linkcode specifier}.

src/lib/to-relative-specifier.mts

+4-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* @module mlly/lib/toRelativeSpecifier
44
*/
55

6+
import toUrl from '#lib/to-url'
67
import type { ModuleId } from '@flex-development/mlly'
78
import pathe from '@flex-development/pathe'
89

@@ -20,7 +21,7 @@ import pathe from '@flex-development/pathe'
2021
* @param {ModuleId} url
2122
* The `file:` URL to convert
2223
* @param {ModuleId} parent
23-
* URL of parent module
24+
* Parent module id
2425
* @return {string}
2526
* Relative specifier
2627
*/
@@ -31,8 +32,8 @@ function toRelativeSpecifier(url: ModuleId, parent: ModuleId): string {
3132
* @var {string} specifier
3233
*/
3334
let specifier: string = pathe.relative(
34-
pathe.fileURLToPath(parent),
35-
pathe.fileURLToPath(url)
35+
pathe.fileURLToPath(toUrl(parent)),
36+
pathe.fileURLToPath(toUrl(url))
3637
)
3738

3839
if (/(?:\.\.\/){2,}/.test(specifier)) {

src/lib/to-url.mts

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* @file toUrl
3+
* @module mlly/lib/toUrl
4+
*/
5+
6+
import canParseUrl from '#lib/can-parse-url'
7+
import { isBuiltin } from '@flex-development/is-builtin'
8+
import type { ModuleId } from '@flex-development/mlly'
9+
import pathe from '@flex-development/pathe'
10+
11+
/**
12+
* Convert `id` to a {@linkcode URL}.
13+
*
14+
* > 👉 **Note**: If `id` cannot be parsed as a `URL` (in conjunction with
15+
* > `parent`) and is also not a [builtin module][builtin-module], it will be
16+
* > assumed to be a path and converted to a [`file:` URL][file-url].
17+
*
18+
* [builtin-module]: https://nodejs.org/api/esm.html#builtin-modules
19+
* [file-url]: https://nodejs.org/api/esm.html#file-urls
20+
*
21+
* @param {ModuleId} id
22+
* The module id to convert
23+
* @param {ModuleId | null | undefined} [parent]
24+
* Base URL to resolve against if `id` is not absolute
25+
* @return {URL}
26+
* New URL
27+
*/
28+
function toUrl(id: ModuleId, parent?: ModuleId | null | undefined): URL {
29+
return canParseUrl(id, parent)
30+
? new URL(id, parent ?? undefined)
31+
: isBuiltin(id)
32+
? new URL('node:' + String(id))
33+
: pathe.pathToFileURL(String(id))
34+
}
35+
36+
export default toUrl

0 commit comments

Comments
 (0)