-
-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix relative link paths in pnpm lockfile #93
Conversation
Co-authored-by: Evan Suhyeong Lee <sounmind@users.noreply.github.com>
return mapValues(def, (value, key) => | ||
value.startsWith("link:") ? `link:./${directoryByPackageName[key]}` : value | ||
); | ||
return mapValues(def, (value, key) => { | ||
if (value.startsWith("link:")) { | ||
let relativePath = path.relative( | ||
importerPath, | ||
directoryByPackageName[key] | ||
); | ||
if (!relativePath.startsWith(".") && !relativePath.startsWith("/")) { | ||
relativePath = `./${relativePath}`; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because directoryByPackageName[key]
is a path relative to the project root, I think we need to add a logic to resolve a relative path from the importer's path.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't quite understand why this check would be necessary:
if (!relativePath.startsWith(".") && !relativePath.startsWith("/"))
- In what scenario does
path.relative()
return a valid path that is not starting with "."? - What valid relative path would start with a "/"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
path.relative
formats the path like "dir1/dir2" instead of "./dir1/dir2". I saw pnpm-lock.yaml file has all path starting with "./" so I added this line.- Good point! I can't think of any case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've tested it and it seems to work for me. If you can simplify the check I can merge this. I suggest to change the function to:
function pnpmMapDependenciesLinks(
importerPath: string,
def: ResolvedDependencies,
directoryByPackageName: { [packageName: string]: string }
): ResolvedDependencies {
return mapValues(def, (value, key) => {
if (!value.startsWith("link:")) {
return value;
}
const relativePath = path.relative(
importerPath,
directoryByPackageName[key]
);
return relativePath.startsWith(".")
? `link:${relativePath}`
: `link:./${relativePath}`;
});
}
Please let met know if you need a reproduction of the problem! |
@0916dhkim What does your monorepo folder structure look like? Note that isolate-package only supports monorepos with a flat packages directory structure. There can be multiple packages container directories, but each needs to be flat. I use isolate-package in projects that have internal dependencies depending on other internal dependencies, so it was designed to handle that, but both packages need to be living in the same parent folder next to each other and not nested. This is also described in prerequisites. |
@0x80 Yes, my company's project is a flat monorepo 👍 I'll put together a small repro repo to demonstrate the issue soon because I cannot share the private code. |
Here is the repro! Let me know if I can provide more details about the error. |
@0916dhkim thanks I'll try to look into it soon. I'm currently travelling and don't have much time behind my computer. |
I found the issue. You need to specify in each package manifest, what files are supposed to be published. This is also described in the readme prerequisites. The paths in the generated pnpm lockfile are correct. They should be relative to the root of the isolate directory, and not to each other. to ./packages/first and ./packages/second are both correct. This is that I added:
Also isolate-package can be a direct dev dependency on the package that you are isolating, so no need to place it in the root. Let me know how you get on... I will make a note to add this files field check and throw and error otherwise. |
@0x80 Thank you! I will try to add files manifest and see if that fixes the issue. |
I tried adding When I look at other open source repos, it seems like pnpm dependencies are linked relative to each importer. Tho I am not 100% sure what is the officially supported behavior. Example:
No rush for a response! I really like the library & the ergonomics of the |
Strange. I don't see the problem yet. If you look at mono-ts, the services/fns package depends on common and backend, but backend also depends on common. I can isolate that package, and do a Maybe you can spot the difference... I'm out of time for now. |
@0x80 I identified the difference! In mono-ts, That is why it runs fine even though the generated |
@0916dhkim Sounds plausible. It would be a major flaw and I'm surprised that you are the first to run into this issue. I will try your fix in the coming days, and added a question to your proposed code. |
Thank you 🙏 |
@0916dhkim Would you like to wrap this up? I'd like to merge your PR before anyone else runs into the problem. I posted a code suggestion, but didn't do an official review + request changes. |
Problem Breakdown
Right now, if you have a monorepo setup with an internal dependency depending on another internal package, the generated
pnpm-lock.yaml
file does not resolve the paths correctly.Let's say we have a dependency tree like this.
@package/to-be-isolated
(located atpackages/to-be-isolated
) ->@package/first
(located atpackages/first
) ->@package/second
(located atpackages/second
)The expected
pnpm-lock.yaml
content isHowever, the actual output is