Reputation: 2186
when you add imports
to an ESM package, you can resolve alias paths into the corresponding real ones, like this:
package.json
{
"type": "module",
"imports": { "#*": "./*" }
...
}
now we can use it like this import something from "#module"
which resolves into import something from "./module"
but, I can't see any docs about using the same resolving mechanism for builtin functions (or maybe user functions either) that accept PathLike arguments like readFileSync
readFileSync("#file.txt")
I know it is a module resolving, but we can use it as a path resolving.
my question is: how to achieve the same mechanism to resolve any PathLike path, without a manual modification, because simply we need to dispense the relative paths
an example of manual resolving
function example(path: PathLike){
let imports = /* read the property imports from package.json */
let keys = Object.keys(imports)
// make a loop, and for each key make something like this (needs additional work)
let resolvedPath = path.replace('#','./')
// now, use resolvedPath instead of path
}
example of nodejs resolving
function example2(path: PathLike){
let resolvedPath = resolve(path)
}
in addition to the original work of resolve() it also uses the property import
to resolve the path to avoid using relative paths
I ask if there is a way to achieve this goal.
The solution
thanks to @RickN this is the final solution:
export function resolveImports(path: PathLike): Promise<string> {
return import.meta!.resolve!(path.toString()).then((resolvedPath) =>
fileURLToPath(resolvedPath)
);
}
Upvotes: 0
Views: 331
Reputation: 13500
As of writing, you need a CLI flag to enable the resolve method in import.meta
:
node --experimental-import-meta-resolve your-file.js
(The first part of the name speaks for itself.)
Then, in a script:
console.log( await import.meta.resolve('#foo/bar.js') );
// It can resolve any type of file, even if you can't import() it.
console.log( await import.meta.resolve('#foo/hello.txt') );
As it's a promise-based function, you'll need to await the result.
async function example2(path: PathLike){
return import.meta.resolve(path);
}
As a side-note: this returns a URL (file:///...
) so run the result through the built-in URL class url.fileURLToPath()
if you just want a file path:
import { fileURLToPath } from 'node:url';
// OR: const { fileURLToPath } = require('node:url');
// For older node versions use `require('url')`
console.log( fileURLToPath(await import.meta.resolve('#foo/hello.txt')) );
// => /tmp/example/directory-with-modules-in-it/hello.txt
Upvotes: 1