类型错误 [ERR_UNKNOWN_FILE_EXTENSION]:

Posted

技术标签:

【中文标题】类型错误 [ERR_UNKNOWN_FILE_EXTENSION]:【英文标题】:TypeError [ERR_UNKNOWN_FILE_EXTENSION]: 【发布时间】:2021-05-12 14:32:22 【问题描述】:

这是我试图运行./bitgo-express --port 3080 --env test --bind localhost 的命令,我收到以下错误:

(node:367854) ExperimentalWarning: The ESM module loader is experimental.
internal/process/esm_loader.js:90
    internalBinding('errors').triggerUncaughtException(
                              ^

TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension "" for /home/root/example.com/BitGoJS/modules/express/bin/bitgo-express
    at Loader.defaultGetFormat [as _getFormat] (internal/modules/esm/get_format.js:65:15)
    at Loader.getFormat (internal/modules/esm/loader.js:116:42)
    at Loader.getModuleJob (internal/modules/esm/loader.js:247:31)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
    at async Loader.import (internal/modules/esm/loader.js:181:17)
    at async Object.loadESM (internal/process/esm_loader.js:84:5) 
  code: 'ERR_UNKNOWN_FILE_EXTENSION'

bitgo-express:

#!/usr/bin/env node

const  init  = require('../src/expressApp.ts');

if (require.main === module) 
  init()
  .catch(err => 
    console.log(`Fatal error: $err.message`);
    console.log(err.stack);
  );

expressApp.ts:

/**
 * @prettier
 */
import * as express from 'express';
import * as httpProxy from 'http-proxy';
import * as url from 'url';
import * as Bluebird from 'bluebird';
import * as path from 'path';
import * as _ from 'lodash';
import * as debugLib from 'debug';
import * as https from 'https';
import * as http from 'http';
import * as morgan from 'morgan';
import * as fs from 'fs';
import  Request as StaticRequest  from 'express-serve-static-core';

import  Config, config  from './config';

const debug = debugLib('bitgo:express');

// eslint-disable-next-line @typescript-eslint/camelcase
import  SSL_OP_NO_TLSv1  from 'constants';
import  IpcError, NodeEnvironmentError, TlsConfigurationError  from './errors';

import  Environments  from 'bitgo';
import  setupRoutes  from './clientRoutes';
const  version  = require('bitgo/package.json');
const pjson = require('../package.json');

const BITGOEXPRESS_USER_AGENT = `BitGoExpress/$pjson.version BitGoJS/$version`;

/**
 * Set up the logging middleware provided by morgan
 *
 * @param app
 * @param config
 */
function setupLogging(app: express.Application, config: Config): void 
  // Set up morgan for logging, with optional logging into a file
  let middleware;
  if (config.logFile) 
    // create a write stream (in append mode)
    const accessLogPath = path.resolve(config.logFile);
    const accessLogStream = fs.createWriteStream(accessLogPath,  flags: 'a' );
    console.log('Log location: ' + accessLogPath);
    // setup the logger
    middleware = morgan('combined',  stream: accessLogStream );
   else 
    middleware = morgan('combined');
  

  app.use(middleware);
  morgan.token('remote-user', function(req) 
    return req.isProxy ? 'proxy' : 'local_express';
  );


/**
 * If we're running in a custom env, set the appropriate environment URI and network properties
 *
 * @param config
 */
function configureEnvironment(config: Config): void 
  const  customRootUri, customBitcoinNetwork  = config;
  if (customRootUri) 
    Environments['custom'].uri = customRootUri;
  

  if (customBitcoinNetwork) 
    Environments['custom'].network = customBitcoinNetwork;
  


/**
 * Create and configure the proxy middleware and add it to the app middleware stack
 *
 * @param app bitgo-express Express app
 * @param config
 */
function configureProxy(app: express.Application, config: Config): void 
  const  env, timeout  = config;

  // Mount the proxy middleware
  const options = 
    timeout: timeout,
    proxyTimeout: timeout,
    secure: true,
  ;

  if (Environments[env].network === 'testnet') 
    // Need to do this to make supertest agent pass (set rejectUnauthorized to false)
    options.secure = false;
  

  const proxy = httpProxy.createProxyServer(options);

  const sendError = (res: http.ServerResponse, status: number, json: object) => 
    res.writeHead(status, 
      'Content-Type': 'application/json',
    );

    res.end(JSON.stringify(json));
  ;

  proxy.on('proxyReq', function(proxyReq, req) 
    // Need to rewrite the host, otherwise cross-site protection kicks in
    const parsedUri = url.parse(Environments[env].uri).hostname;
    if (parsedUri) 
      proxyReq.setHeader('host', parsedUri);
    

    const userAgent = req.headers['user-agent']
      ? BITGOEXPRESS_USER_AGENT + ' ' + req.headers['user-agent']
      : BITGOEXPRESS_USER_AGENT;
    proxyReq.setHeader('User-Agent', userAgent);
  );

  proxy.on('error', (err, _, res) => 
    debug('Proxy server error: ', err);
    sendError(res, 500, 
      error: 'BitGo Express encountered an error while attempting to proxy your request to BitGo. Please try again.',
    );
  );

  proxy.on('econnreset', (err, _, res) => 
    debug('Proxy server connection reset error: ', err);
    sendError(res, 500, 
      error:
        'BitGo Express encountered a connection reset error while attempting to proxy your request to BitGo. Please try again.',
    );
  );

  app.use(function(req: StaticRequest, res: express.Response) 
    if (req.url && (/^\/api\/v[12]\/.*$/.test(req.url) || /^\/oauth\/token.*$/.test(req.url))) 
      req.isProxy = true;
      proxy.web(req, res,  target: Environments[env].uri, changeOrigin: true );
      return;
    

    // user tried to access a url which is not an api route, do not proxy
    res.status(404).send('bitgo-express can only proxy BitGo API requests');
  );


/**
 * Create an HTTP server configured for accepting HTTPS connections
 *
 * @param config application configuration
 * @param app
 * @return Server
 */
async function createHttpsServer(
  app: express.Application,
  config: Config &  keyPath: string; crtPath: string 
): Promise<https.Server> 
  const  keyPath, crtPath  = config;
  const privateKeyPromise = fs.promises.readFile(keyPath, 'utf8');
  const certificatePromise = fs.promises.readFile(crtPath, 'utf8');

  const [key, cert] = await Promise.all([privateKeyPromise, certificatePromise]);

  // eslint-disable-next-line @typescript-eslint/camelcase
  return https.createServer( secureOptions: SSL_OP_NO_TLSv1, key, cert , app);


/**
 * Create an HTTP server configured for accepting plain old HTTP connections
 *
 * @param app
 * @return Server
 */
function createHttpServer(app: express.Application): http.Server 
  return http.createServer(app);


/**
 * Create a startup function which will be run upon server initialization
 *
 * @param config
 * @param baseUri
 * @return Function
 */
export function startup(config: Config, baseUri: string): () => void 
  return function() 
    const  env, ipc, customRootUri, customBitcoinNetwork  = config;
    console.log('BitGo-Express running');
    console.log(`Environment: $env`);
    if (ipc) 
      console.log(`IPC path: $ipc`);
     else 
      console.log(`Base URI: $baseUri`);
    
    if (customRootUri) 
      console.log(`Custom root URI: $customRootUri`);
    
    if (customBitcoinNetwork) 
      console.log(`Custom bitcoin network: $customBitcoinNetwork`);
    
  ;


/**
 * helper function to determine whether we should run the server over TLS or not
 */
function isTLS(config: Config): config is Config &  keyPath: string; crtPath: string  
  const  keyPath, crtPath  = config;
  return Boolean(keyPath && crtPath);


/**
 * Create either a HTTP or HTTPS server
 * @param config
 * @param app
 * @return Server
 */
export async function createServer(config: Config, app: express.Application) 
  return isTLS(config) ? await createHttpsServer(app, config) : createHttpServer(app);


/**
 * Create the base URI where the BitGoExpress server will be available once started
 * @return string
 */
export function createBaseUri(config: Config): string 
  const  bind, port  = config;
  const tls = isTLS(config);
  const isStandardPort = (port === 80 && !tls) || (port === 443 && tls);
  return `http$tls ? 's' : ''://$bind$!isStandardPort ? ':' + port : ''`;


/**
 * Check environment and other preconditions to ensure bitgo-express can start safely
 * @param config
 */
function checkPreconditions(config: Config) 
  const  env, disableEnvCheck, bind, ipc, disableSSL, keyPath, crtPath, customRootUri, customBitcoinNetwork  = config;

  // warn or throw if the NODE_ENV is not production when BITGO_ENV is production - this can leak system info from express
  if (env === 'prod' && process.env.NODE_ENV !== 'production') 
    if (!disableEnvCheck) 
      throw new NodeEnvironmentError(
        'NODE_ENV should be set to production when running against prod environment. Use --disableenvcheck if you really want to run in a non-production node configuration.'
      );
     else 
      console.warn(
        `warning: unsafe NODE_ENV '$process.env.NODE_ENV'. NODE_ENV must be set to 'production' when running against BitGo production environment.`
      );
    
  

  const needsTLS = !ipc && env === 'prod' && bind !== 'localhost' && !disableSSL;

  // make sure keyPath and crtPath are set when running over TLS
  if (needsTLS && !(keyPath && crtPath)) 
    throw new TlsConfigurationError('Must enable TLS when running against prod and listening on external interfaces!');
  

  if (Boolean(keyPath) !== Boolean(crtPath)) 
    throw new TlsConfigurationError('Must provide both keypath and crtpath when running in TLS mode!');
  

  if ((customRootUri || customBitcoinNetwork) && env !== 'custom') 
    console.warn(`customRootUri or customBitcoinNetwork is set, but env is '$env'. Setting env to 'custom'.`);
    config.env = 'custom';
  


export function app(cfg: Config): express.Application 
  debug('app is initializing');

  const app = express();

  setupLogging(app, cfg);

  const  debugNamespace, disableProxy  = cfg;

  // enable specified debug namespaces
  if (_.isArray(debugNamespace)) 
    _.forEach(debugNamespace, ns => debugLib.enable(ns));
  

  checkPreconditions(cfg);

  // Be more robust about accepting URLs with double slashes
  app.use(function(req, res, next) 
    req.url = req.url.replace(/\/\//g, '/');
    next();
  );

  // Decorate the client routes
  setupRoutes(app, cfg);

  configureEnvironment(cfg);

  if (!disableProxy) 
    configureProxy(app, cfg);
  

  return app;


/**
 * Prepare to listen on an IPC (unix domain) socket instead of a normal TCP port.
 * @param ipcSocketFilePath path to file where IPC socket should be created
 */
export async function prepareIpc(ipcSocketFilePath: string) 
  if (process.platform === 'win32') 
    throw new IpcError(`IPC option is not supported on platform $process.platform`);
  

  try 
    const stat = fs.statSync(ipcSocketFilePath);
    if (!stat.isSocket()) 
      throw new IpcError('IPC socket is not actually a socket');
    
    // ipc socket does exist and is indeed a socket. However, the socket cannot already exist prior
    // to being bound since it will be created by express internally when binding. If there's a stale
    // socket from the last run, clean it up before attempting to bind to it again. Arguably, it would
    // be better to do this before exiting, but that gets a bit more complicated when all exit paths
    // need to clean up the socket file correctly.
    fs.unlinkSync(ipcSocketFilePath);
   catch (e) 
    if (e.code !== 'ENOENT') 
      throw e;
    
  


export async function init(): Bluebird<void> 
  const cfg = config();
  const expressApp = app(cfg);

  const server = await createServer(cfg, expressApp);

  const  port, bind, ipc  = cfg;
  const baseUri = createBaseUri(cfg);

  if (ipc) 
    await prepareIpc(ipc);
    server.listen(ipc, startup(cfg, baseUri));
   else 
    server.listen(port, bind, startup(cfg, baseUri));
  

  server.timeout = 300 * 1000; // 5 minutes

Node.js 版本:12.19.1 NPM 版本:6.14.8

我该如何解决这个问题?我看到了这个SyntaxError: Cannot use import statment without a module, TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Catch 22,和我的很相似。但是那个答案对我没有帮助,因为那时我将不得不编辑整个文件,即使我这样做了,我也被困在 38 行。如果有人可以将整个代码翻译成节点友好的需求,请翻译它。非常感谢!

【问题讨论】:

为了执行 TypeScript,你需要先编译它。请参阅here(该教程由 VS Code 编写,但仍适用于您)。 【参考方案1】:

你可以像这样运行你的脚本:

npx ts-node ./path/to/your-script.ts

您可能希望使用 typescript 编译器构建脚本并将构建结果作为普通 JS 脚本运行。 但是为此,您需要设置一些捆绑程序,例如 Webpack,并且您需要配置插件来处理 Typescript 编译,例如您可以使用 Bable。

【讨论】:

以上是关于类型错误 [ERR_UNKNOWN_FILE_EXTENSION]:的主要内容,如果未能解决你的问题,请参考以下文章

js错误类型

js常见错误类型

错题本上的常见错误类型及改正方法

Flutter fromJson - 未处理的错误未处理的错误类型'String'不是'int'类型的子类型发生在实例中

我在尝试登录或注册时收到错误消息“错误类型‘AuthResult’不是类型转换中‘FirebaseUser’类型的子类型”

ASP.NET MVC前台解析JSON时,类型错误