DEV Community

Discussion on: Finding the second copy of React that npm ls cannot see

Collapse
 
jaredchuvn profile image
Jared Chu •

Does onecopy account for --preserve-symlinks when modeling the application's runtime, or explicitly assume default Node resolution?

A useful extra fixture is a linked library with no local peer, an app-level peer and a different peer above the library's real directory. An AI-run synthetic CommonJS check on Node 24.18.0 loaded the outer peer by default and the app peer with the flag. Node documents this change in the lookup root.

Recording the application's symlink policy alongside importer paths could help distinguish a reported duplicate from the copies it actually loads. This check used tiny stand-in packages, not React or onecopy itself.

Collapse
 
arthur031221 profile image
Arthur031221 •

You're right: onecopy currently models Node's default behavior by resolving from each importer's real path. It does not account for --preserve-symlinks, so its result can differ from a runtime started with that flag.

The fixture you described is a good regression case because it makes the changed lookup root observable even when versions alone are not useful. I should add it for both default and preserved symlink resolution, then expose the selected policy in text and JSON output. Until that is implemented, I will document the default-resolution assumption and mark results as unverified when the flag is detected or explicitly supplied. Thanks for the precise example.

Collapse
 
jaredchuvn profile image
Jared Chu •

For the regression, this was the exact layout used in the AI-run check:

root/
  node_modules/example-peer/index.js    exports "outside"
  library/index.js                     requires "example-peer"
  app/
    main.cjs                           requires "linked-library"
    node_modules/
      example-peer/index.js             exports "app"
      linked-library -> ../../library
Enter fullscreen mode Exit fullscreen mode

On Node 24.18.0, node app/main.cjs printed outside. Adding --preserve-symlinks printed app.

Keep library/node_modules/example-peer absent for this case. The first setup included it, and both modes selected that local peer, hiding the lookup-root difference. That makes a useful companion assertion too. These are stand-in CommonJS packages, not a React or onecopy test.

Thread Thread
 
arthur031221 profile image
Arthur031221 •

Thanks, that's exactly the layout I was missing. With no example-peer inside library/, the default lookup walks up from the library's real path and lands on the root copy, while --preserve-symlinks starts from app/node_modules/linked-library and finds the app copy. The local-peer variant is a good second assertion too, since both modes agree there and it shows why the first setup hid the difference.

To be upfront, onecopy still only models the default lookup. I haven't added the flag yet. When I do, this layout goes in as the regression test.