standard-things / esm

Tomorrow's ECMAScript modules today!
Other
5.27k stars 147 forks source link

Error [ERR_INVALID_PROTOCOL]: Protocol 'node:' not supported. Expected 'file:' #904

Open msipinski opened 3 years ago

msipinski commented 3 years ago

Problem:

Using esm to import module that imports builtin Node modules using 'node:*' URL results with an error:

file:///C:/NodeJsProjects/esm-error-test/some-external-module.mjs:1
Error [ERR_INVALID_PROTOCOL]: Protocol 'node:' not supported. Expected 'file:'
    at file:///C:/NodeJsProjects/esm-error-test/some-external-module.mjs:1
    at Generator.next (<anonymous>)

Import with 'node:*' type URL lies inside external package so I can't replace it. Switching my project from CJS to ESM is probably not possible (I'm creating Electron.js app).

Reproducing:

some-external-module.mjs:

import process from 'node:process'

export default process.platform

package.json:

{
  "dependencies": {
    "esm": "^3.2.25"
  }
}

index.mjs:

import platform from './some-external-module.mjs'

console.log('mjs: ' + platform)

index.cjs:

require = require('esm')(module)
const platform = require('./some-external-module.mjs')

console.log('cjs: ' + platform)

Running node index.mjs gives expected output ("mjs: win32"), but running node index.cjs results in error

ioquatix commented 2 years ago

I'm running into the same issue :(

KittyGiraudel commented 2 years ago

Can confirm this happens as well.

ItaloCobains commented 1 year ago

I am also having the same problem.

Using esm to import module that imports builtin Node modules using 'node:*' URL results with an error:

Error [ERR_INVALID_PROTOCOL]: Protocol 'node:' not supported. Expected 'file:'
    at Object.<anonymous> (C:\msys64\home\italo\typi\src\main.js:1)
    at Generator.next (<anonymous>)

Reproducing:

src/main.js:

import ncp from "ncp";
import fs from "node:fs";
import { promisify } from "node:util";

const access = promisify(fs.access);
const copy = promisify(ncp);

async function copyTemplateFiles(options) {
    return copy(options.templateDirectory, options.targetDirectory, {
        clobber: false,
    });
}

export async function createProject(options) {
    options = {
        ...options,
        targetDirectory: options.targetDirectory || process.cwd(),
    };

    const currentFileUrl = import.meta.url;
    const templateDir = path.resolve(
        new URL(currentFileUrl).pathname,
        "../../templates",
        options.template.toLowerCase()
    );
    options.templateDirectory = templateDir;

    try {
        await access(templateDir, fs.constants.R_OK);
    } catch (err) {
        console.log("%s Invalid template name", chalk.red.bold("ERROR"));
        process.exit(1);
    }

    console.log("Copy project files");
    await copyTemplateFiles(options);
    console.log("%s Project ready", chalk.green.bold("DONE"));
    return true;
}

src/cli.js:

import arg from "arg";
import inquirer from "inquirer";
import { createProject } from "./main";

function parseArgumentsIntoOptions(rawArgs) {
    const args = arg(
        {
            "--git": Boolean,
            "--test": Boolean,
            "--lint": Boolean,
            "--yes": Boolean,
            "--install": Boolean,
            "-g": "--git",
            "-t": "--test",
            "-l": "--lint",
            "-y": "--yes",
            "-i": "--install",
        },
        {
            argv: rawArgs.slice(2),
        }
    );

    return {
        skipPrompts: args["--yes"] || false,
        git: args["--git"] || false,
        template: args._[0],
        runInstall: args["--install"] || false,
    };
}

async function promptForMissingOptions(options) {
    const defaultTemplate = "TypeScript";
    if (options.skipPrompts) {
        return {
            ...options,
            template: options.template || defaultTemplate,
        };
    }

    const questions = [];
    if (!options.template) {
        questions.push({
            type: "list",
            name: "template",
            message: "Please choose which project template to use",
            choices: ["JavaScript", "TypeScript"],
            default: defaultTemplate,
        });
    }

    if (!options.git) {
        questions.push({
            type: "confirm",
            name: "git",
            message: "Initialize a git repository?",
            default: false,
        });
    }

    const answars = await inquirer.prompt(questions);
    return {
        ...options,
        template: options.template || answars.template,
        git: options.git || answars.git,
    };
}

export async function cli(args) {
    let options = parseArgumentsIntoOptions(args);
    options = await promptForMissingOptions(options);
    await createProject(options);
}

package.json:

{

    "dependencies": {
        "arg": "^5.0.2",
        "chalk": "^4.1.2",
        "esm": "^3.2.25",
        "inquirer": "^8.0.0",
        "ncp": "^2.0.0"
    }
}

bin/typi:

#!/usr/bin/env node

require = require("esm")(module /*, options*/);
require("../src/cli").cli(process.argv);
sandz9b commented 6 months ago

Is there any update related to this issues? I also got this error (while using an import).

And when I use a require, I got this error while using a "sharp" libraries: Cannot find module 'node:util'

xeoshow commented 4 months ago

Any latest update for this? I also met the same problem, hope esm could support it.