Skip to content
This repository was archived by the owner on Sep 2, 2023. It is now read-only.
This repository was archived by the owner on Sep 2, 2023. It is now read-only.

Node 13.9.0 drop support for extensionless npm scripts ("bin") #488

Closed

Description

package.json:

{
  "scripts": {
    "test": "tsc"
  },
  "dependencies": {
    "typescript": "^3.7.5"
  }
}

.npmrc:

node-options="--loader=./loader.js"

loader.js:

// Custom loader. May be empty for test

Command:

npm test

Result:

Node 13.8.0:

tsc

Node 13.9.0:

tsc
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension "" for c:\workspace\node_13.9.0\node_modules\typescript\bin\tsc
    at Loader.defaultGetFormat [as _getFormat] (internal/modules/esm/get_format.js:70:15)

Why ? Becacuse a lot of tools has bin specification without scripts extension: ex.

  "bin": {
    "tsc": "bin/tsc",
    "tsserver": "bin/tsserver"
  },

Why did you introduce a change that blocks npm scripts?

Activity

  1. MylesBorins commented on Feb 20, 2020

    @MylesBorins
    Contributor

    Can you run node --version locally. There was never a Node.js version 3, as version three was part of the IO.js project. Currently supported versions of Node.js are 10, 12, 13.

    Are you running code as CommonJS or ESM? If you are using ESM you need to include the full path to the resource you are trying to run.

    There is nothing that we have done in Node.js to block npm scripts, which still are actively used across the ecosystem, and if I recall even internally in Node.js core for some of our tooling.

  2. changed the title [-]Node 3.9.0 blocks the use of npm scripts[/-] [+]Node 13.9.0 blocks the use of npm scripts[/+] on Feb 20, 2020
  3. bmeck commented on Feb 20, 2020

    @bmeck
    Member

    This is because --loader forces the ESM resolution algorithm not CJS resolution, and extension-less files are not resolved by default for ESM, see nodejs/node#31415

  4. ghost changed the title [-]Node 13.9.0 blocks the use of npm scripts[/-] [+]Node 13.9.0 blocks the use of npm scripts together with --loader funcionality[/+] on Feb 20, 2020
  5. bmeck commented on Feb 20, 2020

    @bmeck
    Member

    Overall, this is the intended behavior we got to after problems with having support for files lacking extensions in the ESM resolver; so I wouldn't think we need to fix this. My recommendation is you can have tsc map to a file with an extension, or expand the custom --loader supplied to support loading files without extensions (since it is overwriting how tsc works anyway).

  6. guybedford commented on Feb 20, 2020

    @guybedford
    Contributor

    You should be able to work around this by implementing your custom loader to support a get_format hook which allows extensionless files.

    Something like:

    import { extname } from 'path';
    export async function getFormat(url, context, defaultGetFormat) {
      if (!extname(url.pathname)) {
        return {
          format: 'commonjs'
        };
      }
      return defaultGetFormat(url, context, defaultGetFormat);
    }
  7. guybedford commented on Feb 20, 2020

    @guybedford
    Contributor

    Note it would still be an option for us to allow files without an extension for the Node.js CLI entry point only, as we had previously, which was specially implemented before for backwards compatibility cases like this.

  8. bmeck commented on Feb 20, 2020

    @bmeck
    Member

    @guybedford backwards compatibility breakage came from --loader, without --loader it still worked fine

  9. ghost changed the title [-]Node 13.9.0 blocks the use of npm scripts together with --loader funcionality[/-] [+]Node 3.9.0 drop support for extensionless files in CJS using in ESM[/+] on Feb 20, 2020
  10. changed the title [-]Node 3.9.0 drop support for extensionless files in CJS using in ESM[/-] [+]Node 13.9.0 drop support for extensionless files in CJS using in ESM[/+] on Feb 20, 2020
  11. ghost changed the title [-]Node 13.9.0 drop support for extensionless files in CJS using in ESM[/-] [+]Node 13.9.0 drop support for extensionless npm scripts ("bin")[/+] on Feb 21, 2020
  12. tadman commented on Mar 23, 2021

    @tadman

    Fixed some typos in sla100's loader fix and added the import:

    import path from 'path';
    
    export async function getFormat(urlString, context, defaultGetFormat) {
      // support for extensionless files in "bin" scripts
      if (/^file:\/\/\/.*\/bin\//.test(urlString) && !path.extname(urlString)) {
        return {
          format: 'module',
        };
      }
      return defaultGetFormat(urlString, context, defaultGetFormat);
    }

    To use this, node --experimental-loader loader.mjs ... though this does (currently) result in ugly warning messages.

    Is there a more transparent way to include this?

  13. unicornware commented on Oct 1, 2021

    @unicornware

    To use this, node --experimental-loader loader.mjs ... though this does (currently) result in ugly warning messages.

    @tadman it silences all warnings, but i've been using NODE_NO_WARNINGS=1

  14. ghost closed this as completedon Nov 11, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions