anonimitoraf / skerrick

REPL-driven development for NodeJS
GNU General Public License v3.0
103 stars 6 forks source link

Error while starting server: `Cannot find module ...` #6

Open isamert opened 2 years ago

isamert commented 2 years ago

Really cool project, I really wanted something like this for quite a while. But I'm having issues while starting it.

Here is an example setup:

$ npm i -g @nestjs/cli
$ nest new project-name

This gives you an working base NestJS project. Then I tried to run skerrick server, like this:

skerrick 4321 $(pwd)/src/main.ts

Here is the output I got:

Click to expand! ``` --- Port: 4321 --- Entry point /var/folders/pn/_2wjbhjx5y51f0hdx1_r67hm0000gp/T/tmp.XCNl4St8NB/testproj/src/main.ts --- Eval imports? false code transformed: "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.NestFactory = exports.APP_PIPE = exports.APP_INTERCEPTOR = exports.APP_GUARD = exports.APP_FILTER = void 0; const tslib_1 = require("tslib"); /* * Nest @core * Copyright(c) 2017 - 2021 Kamil Mysliwiec * https://nestjs.com * MIT Licensed */ registerValue("/private/var/folders/pn/_2wjbhjx5y51f0hdx1_r67hm0000gp/T/tmp.XCNl4St8NB/testproj/node_modules/@nestjs/core/index.js", "tslib_1", tslib_1); require("reflect-metadata"); tslib_1.__exportStar(require("./adapters"), exports); tslib_1.__exportStar(require("./application-config"), exports); var constants_1 = require("./constants"); registerValue("/private/var/folders/pn/_2wjbhjx5y51f0hdx1_r67hm0000gp/T/tmp.XCNl4St8NB/testproj/node_modules/@nestjs/core/index.js", "constants_1", constants_1); Object.defineProperty(exports, "APP_FILTER", { enumerable: true, get: function () { return constants_1.APP_FILTER; } }); Object.defineProperty(exports, "APP_GUARD", { enumerable: true, get: function () { return constants_1.APP_GUARD; } }); Object.defineProperty(exports, "APP_INTERCEPTOR", { enumerable: true, get: function () { return constants_1.APP_INTERCEPTOR; } }); Object.defineProperty(exports, "APP_PIPE", { enumerable: true, get: function () { return constants_1.APP_PIPE; } }); tslib_1.__exportStar(require("./discovery"), exports); tslib_1.__exportStar(require("./exceptions"), exports); tslib_1.__exportStar(require("./helpers"), exports); tslib_1.__exportStar(require("./injector"), exports); tslib_1.__exportStar(require("./metadata-scanner"), exports); tslib_1.__exportStar(require("./middleware"), exports); tslib_1.__exportStar(require("./nest-application"), exports); tslib_1.__exportStar(require("./nest-application-context"), exports); var nest_factory_1 = require("./nest-factory"); registerValue("/private/var/folders/pn/_2wjbhjx5y51f0hdx1_r67hm0000gp/T/tmp.XCNl4St8NB/testproj/node_modules/@nestjs/core/index.js", "nest_factory_1", nest_factory_1); Object.defineProperty(exports, "NestFactory", { enumerable: true, get: function () { return nest_factory_1.NestFactory; } }); tslib_1.__exportStar(require("./router"), exports); return tslib_1.__exportStar(require("./services"), exports); all imports Map(0) {} ns imports for scope {} ns for scope {} Failed to normalize import path: Error: Cannot find module './app.module' Require stack: - /var/folders/pn/_2wjbhjx5y51f0hdx1_r67hm0000gp/T/tmp.XCNl4St8NB/testproj/src/main.ts at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15) at Function.resolve (node:internal/modules/cjs/helpers:108:19) at normalizeImportPath (/Users/isamert.gurbuz/.npm-packages/lib/node_modules/skerrick/dist/engine.js:443:20) at PluginPass.enter (/Users/isamert.gurbuz/.npm-packages/lib/node_modules/skerrick/dist/engine.js:404:47) at newFn (/Users/isamert.gurbuz/.npm-packages/lib/node_modules/skerrick/node_modules/@babel/traverse/lib/visitors.js:177:21) at NodePath._call (/Users/isamert.gurbuz/.npm-packages/lib/node_modules/skerrick/node_modules/@babel/traverse/lib/path/context.js:53:20) at NodePath.call (/Users/isamert.gurbuz/.npm-packages/lib/node_modules/skerrick/node_modules/@babel/traverse/lib/path/context.js:40:17) at NodePath.visit (/Users/isamert.gurbuz/.npm-packages/lib/node_modules/skerrick/node_modules/@babel/traverse/lib/path/context.js:100:31) at TraversalContext.visitQueue (/Users/isamert.gurbuz/.npm-packages/lib/node_modules/skerrick/node_modules/@babel/traverse/lib/context.js:103:16) at TraversalContext.visitMultiple (/Users/isamert.gurbuz/.npm-packages/lib/node_modules/skerrick/node_modules/@babel/traverse/lib/context.js:72:17) { code: 'MODULE_NOT_FOUND', requireStack: [ '/var/folders/pn/_2wjbhjx5y51f0hdx1_r67hm0000gp/T/tmp.XCNl4St8NB/testproj/src/main.ts' ] } /Users/isamert.gurbuz/.npm-packages/lib/node_modules/skerrick/node_modules/@babel/core/lib/transformation/index.js:45 throw e; ^ Error: Cannot find module './app.module' Require stack: - /var/folders/pn/_2wjbhjx5y51f0hdx1_r67hm0000gp/T/tmp.XCNl4St8NB/testproj/src/main.ts at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15) at Function.resolve (node:internal/modules/cjs/helpers:108:19) at normalizeImportPath (/Users/isamert.gurbuz/.npm-packages/lib/node_modules/skerrick/dist/engine.js:443:20) at PluginPass.enter (/Users/isamert.gurbuz/.npm-packages/lib/node_modules/skerrick/dist/engine.js:404:47) at newFn (/Users/isamert.gurbuz/.npm-packages/lib/node_modules/skerrick/node_modules/@babel/traverse/lib/visitors.js:177:21) at NodePath._call (/Users/isamert.gurbuz/.npm-packages/lib/node_modules/skerrick/node_modules/@babel/traverse/lib/path/context.js:53:20) at NodePath.call (/Users/isamert.gurbuz/.npm-packages/lib/node_modules/skerrick/node_modules/@babel/traverse/lib/path/context.js:40:17) at NodePath.visit (/Users/isamert.gurbuz/.npm-packages/lib/node_modules/skerrick/node_modules/@babel/traverse/lib/path/context.js:100:31) at TraversalContext.visitQueue (/Users/isamert.gurbuz/.npm-packages/lib/node_modules/skerrick/node_modules/@babel/traverse/lib/context.js:103:16) at TraversalContext.visitMultiple (/Users/isamert.gurbuz/.npm-packages/lib/node_modules/skerrick/node_modules/@babel/traverse/lib/context.js:72:17) { code: 'MODULE_NOT_FOUND', requireStack: [ '/var/folders/pn/_2wjbhjx5y51f0hdx1_r67hm0000gp/T/tmp.XCNl4St8NB/testproj/src/main.ts' ] } ```

Then I realized there is an undocumented evalImports , I also tried setting it to true:

skerrick 4321 $(pwd)/src/main.ts true
Click to expand! ``` --- Port: 4321 --- Entry point /var/folders/pn/_2wjbhjx5y51f0hdx1_r67hm0000gp/T/tmp.XCNl4St8NB/testproj/src/main.ts --- Eval imports? true code transformed: "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.NestFactory = exports.APP_PIPE = exports.APP_INTERCEPTOR = exports.APP_GUARD = exports.APP_FILTER = void 0; const tslib_1 = require("tslib"); /* * Nest @core * Copyright(c) 2017 - 2021 Kamil Mysliwiec * https://nestjs.com * MIT Licensed */ registerValue("/private/var/folders/pn/_2wjbhjx5y51f0hdx1_r67hm0000gp/T/tmp.XCNl4St8NB/testproj/node_modules/@nestjs/core/index.js", "tslib_1", tslib_1); require("reflect-metadata"); tslib_1.__exportStar(require("./adapters"), exports); tslib_1.__exportStar(require("./application-config"), exports); var constants_1 = require("./constants"); registerValue("/private/var/folders/pn/_2wjbhjx5y51f0hdx1_r67hm0000gp/T/tmp.XCNl4St8NB/testproj/node_modules/@nestjs/core/index.js", "constants_1", constants_1); Object.defineProperty(exports, "APP_FILTER", { enumerable: true, get: function () { return constants_1.APP_FILTER; } }); Object.defineProperty(exports, "APP_GUARD", { enumerable: true, get: function () { return constants_1.APP_GUARD; } }); Object.defineProperty(exports, "APP_INTERCEPTOR", { enumerable: true, get: function () { return constants_1.APP_INTERCEPTOR; } }); Object.defineProperty(exports, "APP_PIPE", { enumerable: true, get: function () { return constants_1.APP_PIPE; } }); tslib_1.__exportStar(require("./discovery"), exports); tslib_1.__exportStar(require("./exceptions"), exports); tslib_1.__exportStar(require("./helpers"), exports); tslib_1.__exportStar(require("./injector"), exports); tslib_1.__exportStar(require("./metadata-scanner"), exports); tslib_1.__exportStar(require("./middleware"), exports); tslib_1.__exportStar(require("./nest-application"), exports); tslib_1.__exportStar(require("./nest-application-context"), exports); var nest_factory_1 = require("./nest-factory"); registerValue("/private/var/folders/pn/_2wjbhjx5y51f0hdx1_r67hm0000gp/T/tmp.XCNl4St8NB/testproj/node_modules/@nestjs/core/index.js", "nest_factory_1", nest_factory_1); Object.defineProperty(exports, "NestFactory", { enumerable: true, get: function () { return nest_factory_1.NestFactory; } }); tslib_1.__exportStar(require("./router"), exports); return tslib_1.__exportStar(require("./services"), exports); all imports Map(0) {} ns imports for scope {} ns for scope {} Failed to normalize import path: Error: Cannot find module './app.module' Require stack: - /var/folders/pn/_2wjbhjx5y51f0hdx1_r67hm0000gp/T/tmp.XCNl4St8NB/testproj/src/main.ts at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15) at Function.resolve (node:internal/modules/cjs/helpers:108:19) at normalizeImportPath (/Users/isamert.gurbuz/.npm-packages/lib/node_modules/skerrick/dist/engine.js:443:20) at PluginPass.enter (/Users/isamert.gurbuz/.npm-packages/lib/node_modules/skerrick/dist/engine.js:404:47) at newFn (/Users/isamert.gurbuz/.npm-packages/lib/node_modules/skerrick/node_modules/@babel/traverse/lib/visitors.js:177:21) at NodePath._call (/Users/isamert.gurbuz/.npm-packages/lib/node_modules/skerrick/node_modules/@babel/traverse/lib/path/context.js:53:20) at NodePath.call (/Users/isamert.gurbuz/.npm-packages/lib/node_modules/skerrick/node_modules/@babel/traverse/lib/path/context.js:40:17) at NodePath.visit (/Users/isamert.gurbuz/.npm-packages/lib/node_modules/skerrick/node_modules/@babel/traverse/lib/path/context.js:100:31) at TraversalContext.visitQueue (/Users/isamert.gurbuz/.npm-packages/lib/node_modules/skerrick/node_modules/@babel/traverse/lib/context.js:103:16) at TraversalContext.visitMultiple (/Users/isamert.gurbuz/.npm-packages/lib/node_modules/skerrick/node_modules/@babel/traverse/lib/context.js:72:17) { code: 'MODULE_NOT_FOUND', requireStack: [ '/var/folders/pn/_2wjbhjx5y51f0hdx1_r67hm0000gp/T/tmp.XCNl4St8NB/testproj/src/main.ts' ] } /Users/isamert.gurbuz/.npm-packages/lib/node_modules/skerrick/node_modules/@babel/core/lib/transformation/index.js:45 throw e; ^ Error: Cannot find module './app.module' Require stack: - /var/folders/pn/_2wjbhjx5y51f0hdx1_r67hm0000gp/T/tmp.XCNl4St8NB/testproj/src/main.ts at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15) at Function.resolve (node:internal/modules/cjs/helpers:108:19) at normalizeImportPath (/Users/isamert.gurbuz/.npm-packages/lib/node_modules/skerrick/dist/engine.js:443:20) at PluginPass.enter (/Users/isamert.gurbuz/.npm-packages/lib/node_modules/skerrick/dist/engine.js:404:47) at newFn (/Users/isamert.gurbuz/.npm-packages/lib/node_modules/skerrick/node_modules/@babel/traverse/lib/visitors.js:177:21) at NodePath._call (/Users/isamert.gurbuz/.npm-packages/lib/node_modules/skerrick/node_modules/@babel/traverse/lib/path/context.js:53:20) at NodePath.call (/Users/isamert.gurbuz/.npm-packages/lib/node_modules/skerrick/node_modules/@babel/traverse/lib/path/context.js:40:17) at NodePath.visit (/Users/isamert.gurbuz/.npm-packages/lib/node_modules/skerrick/node_modules/@babel/traverse/lib/path/context.js:100:31) at TraversalContext.visitQueue (/Users/isamert.gurbuz/.npm-packages/lib/node_modules/skerrick/node_modules/@babel/traverse/lib/context.js:103:16) at TraversalContext.visitMultiple (/Users/isamert.gurbuz/.npm-packages/lib/node_modules/skerrick/node_modules/@babel/traverse/lib/context.js:72:17) { code: 'MODULE_NOT_FOUND', requireStack: [ '/var/folders/pn/_2wjbhjx5y51f0hdx1_r67hm0000gp/T/tmp.XCNl4St8NB/testproj/src/main.ts' ] } ```

Maybe skerrick isn't supposed to work for projects like this? If that's the case, it may be nice to have a section describing under what circumstances skerrick works to the README.

anonimitoraf commented 2 years ago

Thanks for raising an issue!

2 things:

If that's the case, it may be nice to have a section describing under what circumstances skerrick works to the README. Good idea. Although, I'll really try to support as many things as I can :)

I'll replicate this later and attempt to fix it. Is it possible to create a non-Typescript NestJS project?

PS: Whoops, I forgot to document evalImports

anonimitoraf commented 2 years ago

Ok, I've confirmed that this issue's because of Typescript not being supported (yet - next on the roadmap though :D)

Although I did run skerrick on the dist folder. Runs fine but when I update/eval nest controller/module code, it doesn't update the endpoint (e.g. I changed return Hello World -> return Hello World!!!! but doesn't take into effect). I'll investigate further.

This is a really good edge case :). I'm determined to get it working

isamert commented 2 years ago

I'll replicate this later and attempt to fix it. Is it possible to create a non-Typescript NestJS project?

AFAIK, yes. But I guess nest CLI tool does not bootstrap one for you, it's probably easier to use dist/ folder for testing as you did.

Ok, I've confirmed that this issue's because of Typescript not being supported (yet - next on the roadmap though :D)

Good to know! Quite exciting. I have some simple snippets that uses tree-sitter which I use for selecting typescript expressions automatically to send to REPL (like eval-last-sexp but for typescript and does some assumptions about what you are trying to evaluate), maybe we can incorporate those into skerrick.el or I can turn them into a package that works with skerrick.el. I believe the snippets can be easily adopted for JS too.

Although I did run skerrick on the dist folder. Runs fine but when I update/eval nest controller/module code, it doesn't update the endpoint (e.g. I changed return Hello World -> return Hello World!!!! but doesn't take into effect). I'll investigate further.

Can you give some workflow related tips regarding to skerrick? Like, lets say that I have changed a function inside a class, I guess I need to re-evaluate whole module or whole class to reflect the changes, right? As far as I understand, skerrick replaces the top-level definitions by it's name, inside the given module. ...and what about module systems, which ones does skerrick support or does it work independently of the module system somehow?

This is a really good edge case :). I'm determined to get it working

Thanks for investigating this issue in detail!

anonimitoraf commented 2 years ago

Re: snippets Sweet as! Feel free to suggest ways to incorporate those snippets. It'd be nice to have CIDER-like niceties for skerrick

Re: workflow Yeah, you'll have to evaluate the whole class at least.

As far as I understand, skerrick replaces the top-level definitions by it's name, inside the given module Yep and what about module systems, which ones does skerrick support or does it work independently of the module system somehow?

I'm planning to support both ES and commonjs modules (I've got the basic stuff working I believe - import, export (defaults, ns, members) and the cjs equivalents. For cjs, I've got a few things I need to finish up (see https://github.com/anonimitoraf/skerrick/blob/main/notes.org). Also check out the tests I've got https://github.com/anonimitoraf/skerrick/tree/main/server/test/evaluate.

As for the module system implementation - they're somewhat combined. The current implementation just simply tracks the values within each namespace/modules, regardless of how it's exported/imported.

isamert commented 2 years ago

I wasn't aware of that notes.org file, will be tracking the updates from there. Also thanks for pointing me to the tests.

anonimitoraf commented 2 years ago

I understand the cause btw. Seems to only happen for commonjs exports/requires. The exported value gets cached as a namespace value (rather than just as an export) and doesn't get updated (even if you re-eval the export).

The problem with commonjs requires is the fact that babel doesn't have a dedicated ParseTree node for it (compared to ES imports which do) so I'll have to find a way to detect a commonjs require and intercept it accordingly

anonimitoraf commented 2 years ago

Ok, so my plan of attack for this is:

So far, the most promising babel plugin for commonjs -> ES module transformation is https://gitlab.com/anonimitoraf/babel-plugin-transform-commonjs-es2015-modules but it seems to fail in a few cases like:

const binding = require('node-gyp-build')(__dirname)

where the RHS isn't a simple require('this')

so I might extend it/fix it up

For requires, so far, these cases seem to fail image