Skip to content

Commit

Permalink
chore: add list command plugin for yarn to fix vsce issue (#36)
Browse files Browse the repository at this point in the history
  • Loading branch information
Simek authored Jan 8, 2025
1 parent ef1ad02 commit aa89ad4
Show file tree
Hide file tree
Showing 2 changed files with 131 additions and 0 deletions.
126 changes: 126 additions & 0 deletions .yarn/plugins/plugin-list.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
module.exports = {
name: "plugin-list",
factory: (require) => {
const fs = require("fs");
const { BaseCommand } = require("@yarnpkg/cli");
const { Command, Option } = require("clipanion");
const { parseSyml } = require("@yarnpkg/parsers");

class ListCommand extends BaseCommand {
static paths = [["list"]];

static usage = Command.Usage({
description: "Lists installed packages.",
});

prod = Option.Boolean("--prod", false);
json = Option.Boolean("--json", false);

async execute() {
if (!this.prod || !this.json) {
throw new Error(
"This command can only be used with the --prod and --json " +
"args to match the behavior required by VSCE. See: " +
"https://github.com/microsoft/vscode-vsce/blob/main/src/npm.ts",
);
}

const packageJsonContents = fs.readFileSync("package.json", "utf-8");
const { dependencies = {}, resolutions = {} } =
JSON.parse(packageJsonContents);

const lockContents = fs.readFileSync("yarn.lock", "utf-8");
const resolved = parseSyml(lockContents);

const trees = [];

function addDependency(packageName, versionRange) {
const packageInfo = lookup(
resolved,
getLockFileKey(packageName, versionRange, resolutions),
);
if (!packageInfo) {
throw new Error(
`Cannot resolve "${packageName}" with version range "${versionRange}"`,
);
}

const { version, dependencies } = packageInfo;
const name = `${packageName}@${version}`;
if (trees.find((tree) => tree.name === name)) {
return; // Dependency already added as part of another tree.
}

if (dependencies) {
const children = Object.entries(dependencies).map(
([name, range]) => ({ name: `${name}@${range}` }),
);
trees.push({ name, children });

addDependencies(dependencies);
} else {
trees.push({ name, children: [] });
}
}

function addDependencies(dependencies) {
for (const [packageName, versionRange] of Object.entries(
dependencies,
)) {
addDependency(packageName, versionRange);
}
}

addDependencies(dependencies);

const output = {
type: "tree",
data: { type: "list", trees },
};

this.context.stdout.write(JSON.stringify(output));
}
}

return {
commands: [ListCommand],
};
},
};

function getLockFileKey(packageName, versionSpecifier, resolutions) {
// If the package name is in the resolutions field, use the version from there.
const resolvedVersionSpecifier = resolutions[packageName] ?? versionSpecifier;

// If the version field contains a URL, don't attempt to use the NPM registry
return resolvedVersionSpecifier.includes(":")
? `${packageName}@${resolvedVersionSpecifier}`
: `${packageName}@npm:${resolvedVersionSpecifier}`;
}

/**
* @param resolved All the resolved dependencies as found in the lock file.
* @param dependencyKey Key of the dependency to look up. Can be created using
* `getLockFileKey()`.
*/
function lookup(resolved, dependencyKey) {
const packageInfo = resolved[dependencyKey];
if (packageInfo) {
return packageInfo;
}

// Fall back to slower iteration-based lookup for combined keys.
for (const [key, packageInfo] of Object.entries(resolved)) {
// Resolving ranges: "@babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5"
const versionRanges = key.split(",");
if (versionRanges.some((key) => key.trim() === dependencyKey)) {
return packageInfo;
}

// Resolving yarn link resolutions: "@kaoto/kaoto-ui@portal:/home/rmartinez/repos/kaoto-ui::locator=vscode-kaoto%40workspace%3A."
const yarnLinkResolution = key.split("::")[0];
if (yarnLinkResolution === dependencyKey) {
return packageInfo;
}
}
}
5 changes: 5 additions & 0 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
nodeLinker: node-modules

plugins:
- checksum: 113fae572c391623e3032d2be1c3eac64ca8d00cfb7fa62a4dab433b87bb66864a577acad63c0a16895869930a41587f409d9de2de69fd1ad539dee6ea9c6bdf
path: .yarn/plugins/plugin-list.cjs
spec: "https://github.com/arendjr/yarn-plugin-list/releases/latest/download/yarn-plugin-list.js"

yarnPath: .yarn/releases/yarn-4.6.0.cjs

0 comments on commit aa89ad4

Please sign in to comment.