Skip to content

Commit

Permalink
feat: support extensions and index resolution
Browse files Browse the repository at this point in the history
  • Loading branch information
pi0 committed Jul 22, 2021
1 parent e0b82cc commit 8f4c080
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 1 deletion.
3 changes: 3 additions & 0 deletions README.md
Expand Up @@ -42,6 +42,8 @@ const { __dirname, __filename, require } = createCommonJS(import.meta)
Resolve a module by respecting [ECMAScript Resolver algorithm](https://nodejs.org/dist/latest-v14.x/docs/api/esm.html#esm_resolver_algorithm)
(internally using [wooorm/import-meta-resolve](https://github.com/wooorm/import-meta-resolve) that exposes Node.js implementation).
Additionally supports resolving without extension and `/index` similar to CommonJS.
```js
import { resolve } from 'mlly'

Expand All @@ -53,6 +55,7 @@ console.log(await resolve('./module.mjs', { from: import.meta.url }))
- `from`: URL or string (default is `pwd()`)
- `conditions`: Array of conditions used for resolution algorithm (default is `['node', 'import']`)
- `extensions`: Array of additional extensions to check if import failed (default is `['.mjs', '.cjs', '.js', '.json']`)
### `resolvePath`
Expand Down
45 changes: 44 additions & 1 deletion lib/index.mjs
Expand Up @@ -28,17 +28,60 @@ export function createCommonJS (importMeta) {
const DEFAULT_CONDITIONS_SET = new Set(['node', 'import'])
const BUILُTIN_MODULES = new Set(builtinModules)
const DEFAULT_FROM = pathToFileURL(process.cwd())
const DEFAULT_EXTENSIONS = ['.mjs', '.cjs', '.js', '.json']

function _tryModuleResolve (id, from, conditions, throwNonNotFound) {
try {
return moduleResolve(id, from, conditions)
} catch (err) {
if (throwNonNotFound && !['MODULE_NOT_FOUND', 'ERR_UNSUPPORTED_DIR_IMPORT'].includes(err.code)) {
throw err
}
return null
}
}

function _resolve (id, opts = {}) {
// console.log('> resolve ', id, 'from', opts.from)

// Skip if already has a protocol
if (/(node|data|http|https):/.test(id)) {
return id
}

// Skip builtins
if (BUILُTIN_MODULES.has(id)) {
return 'node:' + id
}

// Defaults
const conditionsSet = opts.conditions ? new Set(opts.conditions) : DEFAULT_CONDITIONS_SET
const resolved = moduleResolve(id, opts.from ? normalizeid(opts.from) : DEFAULT_FROM, conditionsSet)
const from = opts.from ? normalizeid(opts.from) : DEFAULT_FROM

// Try simple resolve
// Might throw error if error is other than MODULE_NOT_FOUND
let resolved = _tryModuleResolve(id, from, conditionsSet, true)

// Try other extensions if not found
if (!resolved) {
for (const prefix of ['', '/index']) {
for (const ext of DEFAULT_EXTENSIONS || opts.extensions) {
resolved = _tryModuleResolve(id + prefix + ext, from, conditionsSet)
if (resolved) {
break
}
}
}
}

// Throw error if not found
if (!resolved) {
const err = new Error(`Cannot find module ${id} imported from ${from}`)
err.code = 'MODULE_NOT_FOUND'
throw err
}

// Resolve realPath and normalize slash
const realPath = realpathSync(fileURLToPath(resolved))
return pathToFileURL(realPath).toString()
}
Expand Down
1 change: 1 addition & 0 deletions test/foo/index.mjs
@@ -0,0 +1 @@
console.log(import.meta.url)
1 change: 1 addition & 0 deletions test/resolve.mjs
Expand Up @@ -4,5 +4,6 @@ import.meta.resolve = createResolve({ from : import.meta.url })
console.log(await import.meta.resolve('./cjs.mjs'))

console.log(await resolvePath('./cjs.mjs', { from: import.meta.url }))
console.log(await resolvePath('./foo', { from: import.meta.url }))

console.log(await resolveImports(`import foo from './eval.mjs'`, { from: import.meta.url }))

0 comments on commit 8f4c080

Please sign in to comment.