hypermod-io / hypermod-community

Community-owned global registry and documentation hub for codemods. Write & run codemods, share them with your friends!
https://hypermod.io
MIT License
134 stars 18 forks source link

Error: Cannot find module 'utils' when executing local transform #146

Open EliteUser opened 1 year ago

EliteUser commented 1 year ago

Hello, trying to use your codeshift-cli, but faced a problem. I created an example of my codemode repo - https://stackblitz.com/edit/node-uhcfpx?file=index.ts

Here I have a src folder which contains all version transforms. Each has its own motions and so on. Also there is a utils folder with some functions I need across all transformations.

So I'm trying to execute local transform, but getting some errors: 1) Trying to execute codeshift -t ./src/3.0.0/transform.ts ./tmp/foo.tsx - getting an Error: Cannot find module './src/3.0.0/transform.ts'. Looks like cli cannot find a transform file for some reason. Maybe I'm doing something wrong. 2) Trying to execute codeshift ./tmp/foo.tsx - it says that "No transforms specified" but then it gives me a prompt where I can choose a transformation (3.0.0) and then it throws an Error: Cannot find module 'utils'. In my project I have a utils folder and I use it in my transformations, but for some reason cli can not resolve it. 3) Tests with jest works fine, so looks like jest can successfully run my codemode with utils (run jest in console is ok)

Could you please help me to understand and find a problem?

danieldelcore commented 1 year ago

Hey @EliteUser, thanks for raising an issue!

Having a look at the code now and noticed Error: Cannot find module 'utils' is caused by an incorrect import in src/3.0.0/transform.ts & src/3.0.0/motions/test-motion/test-motion.ts.

// src/3.0.0/transform.ts
-import { applyMotions } from 'utils';
+import { applyMotions } from '../../utils';
// src/3.0.0/motions/test-motion/test-motion.ts
-import { renameImportSpecifier } from 'utils';
+import { renameImportSpecifier } from '../../../../utils';

I think you might be expecting this to work via webpack's import alias which isn't setup in this particular repo. To replicate it here, you will have to setup webpack, however IMO the simple relative import approach is best.

Trying to execute codeshift -t ./src/3.0.0/transform.ts ./tmp/foo.tsx - getting an Error: Cannot find module './src/3.0.0/transform.ts'

This is a strange one, this should be working given it passes the transform directly to jscodeshift, I'll have to investigate. However, looks like, as you said, codeshift ./tmp/foo.tsx works in the meantime 🤔. I'll check that and get back to you regardless 😄

Here's a link to a working repro: https://stackblitz.com/edit/node-cufcnk?file=src/3.0.0/motions/test-motion/test-motion.ts Let me know if you run into any other issues!

Cheers, Dan.

EliteUser commented 1 year ago

Hello thank you for the answer! I think I don't need webpack here, because my repo will be just a cli script. I know, that relative path to utils works, but it is not good approach, because I'm using it in other places, so it will end writing ../../../../utils which is a good candidate for tsconfig's paths. But as I said, it looks like paths works only for checking an resolving in my ide, but when I'm trying to execute transform it says "sorry, I don't undermstand 😢". I think that tsconfig-paths may help, but I don't understand how to make this thing work, and not sure it will help at all 😄. By the way, tests works fine, so it seems that jest can recognize paths, why node cant?

danieldelcore commented 1 year ago

Oohh now I understand, this is actually because jscodeshift has an internal tsconfig for parsing typescript files which can be found here: https://github.com/facebook/jscodeshift/blob/main/parser/tsOptions.js . Making it really hard to customise from the outside.

One way you can work around this is to transpile your TS files into javascript, similar to what we do with more typical web applications.

For example:

For what it's worth, @codeshift/cli does this for you already (except for the custom paths).

All you need to do is run:

npx @codeshift/cli init <project-dir>

Optionally you can then run the following to create a transform automatically 😄

npx @codeshift/cli init <project-dir> --transform 1.0.0

image
danieldelcore commented 1 year ago

That being said, I think the dist that is currently output isn't exactly right, so I'll need to create a ticket to update it make this automatic in the future.

synoptase commented 1 year ago

Adding my stone.

Given the following:

Capture d’écran 2023-03-21 à 14 50 35

codeshift.config.js

module.exports = {
  maintainers: [],
  targets: [],
  description: '',
  transforms: {
    'legacy-avatar': require.resolve('./dist/legacy-avatar'),
    'legacy-checkbox': require.resolve('./dist/legacy-checkbox'),
    'legacy-icon': require.resolve('./dist/legacy-icon'),
  },
  presets: {},
};

This command fails:

❯ pwd
/Users/xxxxx/Dev/search/packages/codemods

❯ codeshift -t ./dist/legacy-checkbox/index.js  ../shared/components/MyFile.js -p babel
Running transform: ./dist/legacy-checkbox/index.js
Processing 1 files...
Spawning 1 workers...
Sending 1 files to free worker...
node:internal/modules/cjs/loader:998
  throw err;
  ^

Error: Cannot find module './dist/legacy-checkbox/index.js'
Require stack:
- /Users/xxxxx/.config/yarn/global/node_modules/jscodeshift/src/Worker.js
    at Module._resolveFilename (node:internal/modules/cjs/loader:995:15)
    at Module._load (node:internal/modules/cjs/loader:841:27)
    at Module.require (node:internal/modules/cjs/loader:1061:19)
    at require (node:internal/modules/cjs/helpers:103:18)
    at setup (/Users/xxxxx/.config/yarn/global/node_modules/jscodeshift/src/Worker.js:91:18)
    at Object.<anonymous> (/Users/xxxxx/.config/yarn/global/node_modules/jscodeshift/src/Worker.js:45:3)
    at Module._compile (node:internal/modules/cjs/loader:1159:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1213:10)
    at Module.load (node:internal/modules/cjs/loader:1037:32)
    at Module._load (node:internal/modules/cjs/loader:878:12) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    '/Users/xxxxx/.config/yarn/global/node_modules/jscodeshift/src/Worker.js'
  ]
}

Node.js v18.12.1
All done.
Results:
0 errors
0 unmodified
0 skipped
0 ok
Time elapsed: 0.257seconds

While this succeeds:

codeshift ../shared/components/MyFile.js -p babel