我正在尝试将我的 commonjs 存储库转换为 ESM,但在使用
readFileSync
命令时遇到问题。看来我在节点 18 和节点 20 上得到了不同的行为。我尝试加载路径:
D:\dev\ts-command-line-args\README.MD
我收到一个错误:
错误 [ERR_UNSUPPORTED_ESM_URL_SCHEME]:默认 ESM 加载程序仅支持具有以下方案的 URL:文件和数据。在 Windows 上,绝对路径必须是有效的 file:// URL。收到协议“d:”
然后我给它一个带有模式的路径:
const markdownPath = pathToFileURL(resolve(args.markdownPath)).href;
console.log(`Loading existing file from '${chalk.blue(markdownPath)}'`);
const markdownFileContent = readFileSync(markdownPath).toString();
然后我在节点 18 上收到此错误:
Loading existing file from 'file:///D:/dev/ts-command-line-args/README.MD'
node:fs:601
handleErrorFromBinding(ctx);
^
Error: ENOENT: no such file or directory, open 'file:///D:/dev/ts-command-line-args/README.MD'
at Object.openSync (node:fs:601:3)
at readFileSync (node:fs:469:35)
at writeMarkdown (file:///D:/dev/ts-command-line-args/dist/write-markdown.js:15:33)
at file:///D:/dev/ts-command-line-args/dist/write-markdown.js:46:1
at ModuleJob.run (node:internal/modules/esm/module_job:194:25) {
errno: -4058,
syscall: 'open',
code: 'ENOENT',
path: 'file:///D:/dev/ts-command-line-args/README.MD'
}
(文件肯定存在)
节点 20 上出现此错误:
Error: ENOENT: no such file or directory, open 'D:\dev\ts-command-line-args\file:\D:\dev\ts-command-line-args\README.MD'
更复杂的是,我的项目已经使用几乎相同的方法加载了一个文件:
console.log(`Loading args from file ${resolve(parsedArgs[options.loadFromFileArg])}`);
const configFromFile: Partial<Record<keyof T, any>> = JSON.parse(
readFileSync(resolve(parsedArgs[options.loadFromFileArg])).toString(),
);
从文件 D:\dev s-command-line-args\package.json 加载参数
此工作代码位于
parse.js
中。我正在运行此代码:
节点分布/写标记
write-markdown.js
进口parse.js
:
import { parse } from './parse.js';
所以看起来(这是一个假设)在由节点直接运行的js文件中加载文件不起作用,但在导入的js文件中加载文件确实起作用......
我真的希望有人能为我解决这个问题!
你在追逐一条红鲱鱼。检查错误堆栈并查看错误来自何处始终很重要!
您的
ERR_UNSUPPORTED_ESM_URL_SCHEME
错误的完整堆栈是这样的:
Error [ERR_UNSUPPORTED_ESM_URL_SCHEME]: Only URLs with a scheme in: file, data are supported by the default ESM loader. On Windows, absolute paths must be valid file:// URLs. Received protocol 'c:'
at new NodeError (node:internal/errors:372:5)
at throwIfUnsupportedURLScheme (node:internal/modules/esm/resolve:1078:11)
at defaultResolve (node:internal/modules/esm/resolve:1158:3)
at ESMLoader.resolve (node:internal/modules/esm/loader:605:30)
at ESMLoader.getModuleJob (node:internal/modules/esm/loader:318:18)
at ESMLoader.import (node:internal/modules/esm/loader:404:22)
at importModuleDynamically (node:internal/modules/esm/translators:106:35)
at importModuleDynamicallyCallback (node:internal/process/esm_loader:35:14)
at loadArgConfig (file:///C:/Users/david/Temp/ts-command-line-args/dist/helpers/markdown.helper.js:121:23)
at file:///C:/Users/david/Temp/ts-command-line-args/dist/helpers/markdown.helper.js:114:42 {
code: 'ERR_UNSUPPORTED_ESM_URL_SCHEME'
}
重要的部分是:
at loadArgConfig (file:///C:/Users/david/Temp/ts-command-line-args/dist/helpers/markdown.helper.js:121:23)
...引用此代码:
export async function loadArgConfig(jsFile: string, importName: string): Promise<UsageGuideConfig | undefined> {
const jsPath = join(process.cwd(), jsFile);
// eslint-disable-next-line @typescript-eslint/no-var-requires
const jsExports = await import(jsPath); // <------------------- ERROR HERE!!!
const argConfig: UsageGuideConfig = jsExports[importName];
if (argConfig == null) {
console.warn(`Could not import ArgumentConfig named '${importName}' from jsFile '${jsFile}'`);
return undefined;
}
return argConfig;
}
它与
write-markdown.ts
文件及其对readFileSync
的使用无关!不过,您更改了另一个文件中的代码,这更改了错误,因为您在运行此文件之前之前的代码中引入了一个新错误,因此现在它更早失败了。
解决方案是保留与
readFileSync
相关的代码,因为它工作得很好(没有 pathToFileURL
),而是在 pathToFileURL
中使用 loadArgConfig
(错误抱怨的地方):
const jsExports = await import(pathToFileURL(jsPath).href);
查看我的拉取请求https://github.com/Roaders/ts-command-line-args/pull/45