exuanbo / module-from-string

Load module from string using require or import.
MIT License
47 stars 2 forks source link

Cannot read property 'path' of undefined #13

Closed YoSev closed 2 years ago

YoSev commented 2 years ago

hello,

i want to use importFromStringSync but require.main is undefined (i use es2020 and type: module).

const { greet } = importFromStringSync(
          content,
          { transformOptions: { loader: 'ts', sourcefile: "file://./node/wave/src/nodes/actions/console" } }
      )

the important part for me is, that i can provide a filepath where the context lives as i use relative imports within that content. Apparantly, 'sourcefile' has no effect.

Content:

import ActionNode from "../ActionNode.js";
import {
  StreamNodeSpecification
} from "../../../models/StreamNodeSpecification.js";

export default class ConsoleLogAction extends ActionNode {
  protected specification: StreamNodeSpecification = {
    name: "Console Log Action",
  };

  async execute(): Promise<void> {
  }
}

Any ideas?

YoSev commented 2 years ago

Addition: i managed to import the file if i do not rely on require.main (i replaced your code temporary = hardcoded filename) but the import failed as the relative path won't work.

exuanbo commented 2 years ago

Yes, this is a bug. It doesn't work in ES module context.

Relative path import depends on createRequire(fileName), I think it should work if you hardcoded it.

I will look into this problem.

YoSev commented 2 years ago

I kind of rely on ES module import and the moduleFromString stuff is driving me nuts.. thanks

exuanbo commented 2 years ago

Hello,

I fixed this in the pre-release version 3.1.0-0. You can install it and give it a try.

By now only requireFromString and asynchronous importFromString are supported. Executing node with --experimental-vm-modules command flag is required.

YoSev commented 2 years ago

Hey,

this seems to work way better already. To be fair, i didnt execute node with --experimental-vm-modules as i thought its not required anymore for node 16.x, i was wrong.

I read the transform API doc but i still don't know how to present the target directory the code-from-string should "live" in. I tried some combinations like:

const result = await importFromString(code, {
          globals: { process },
          transformOptions: {
            loader: "ts",
            format: "esm",
            sourcefile:
              "file:///./nodes/actions/console/Console.js",
          },
        });

The import itself works fine but my codes doesn't as it's trying to import other relative paths which can not be found anymore.

The error looks like this:

ERR_MODULE_NOT_FOUND /Users/x/project/node:internal/ActionNode.js 

No idea where node:internal comes from. Setting the sourcefile to something completly different doesn't change anything.

This is the code im importing right now: https://pastebin.com/raw/AMdU0N6M

Can you point me in the right direction?

P.S. using aboslute paths within the pastebin code works fine.

YoSev commented 2 years ago

Nevermind, i just saw you added dirname? next to globals? which does exactly what i want. Thanks, i appreciate your work!

exuanbo commented 2 years ago

Yes I forgot to mention dirname. It is used to resolve relative path import.

Actually this is a bug and I will fix it in the next version.

If you wonder where node:internal is from...

explanation When `dirname` is not provided, the directory path is get from the file path from V8 stack trace api. Similar to this ``` Error at getCallerDirname (file:///Users/xuanbo/repositories/module-from-string/dist/index.mjs:22:17) at importFromString (file:///Users/xuanbo/repositories/module-from-string/dist/index.mjs:70:84) at file:///Users/xuanbo/repositories/module-from-string/test-esm/index.js:3:19 at ModuleJob.run (internal/modules/esm/module_job.js:170:25) at async Loader.import (internal/modules/esm/loader.js:178:24) at async Object.loadESM (internal/process/esm_loader.js:68:5) ``` The stack trace will be like this if `transformOptions` is provided, which I didn't expect ``` Error at getCallerDirname (file:///Users/xuanbo/repositories/module-from-string/dist/index.mjs:22:17) at importFromString (file:///Users/xuanbo/repositories/module-from-string/dist/index.mjs:70:84) at processTicksAndRejections (internal/process/task_queues.js:95:5) at async file:///Users/xuanbo/repositories/module-from-string/test-esm/index.js:3:13 ```