Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions bundles/@yarnpkg/plugin-catalogs.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion sources/__tests__/validation.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { describe, it, expect, afterEach } from "vitest";
import {
createTestWorkspace,
TestWorkspace,
type TestWorkspace,
extractDependencies,
} from "./utils";

Expand Down
43 changes: 41 additions & 2 deletions sources/__tests__/warnings.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ describe("warnings and recommendations", () => {
expect(dependencies).includes("react@npm:18.0.0");
});

it("should warn when adding a dependency not in the default alias group", async () => {
it("should not warn when adding a dependency not in the default alias group", async () => {
workspace = await createTestWorkspace();

await workspace.writeYarnrc({
Expand All @@ -115,7 +115,7 @@ describe("warnings and recommendations", () => {

await workspace.yarn.add("react");
const { stderr } = await workspace.yarn.add("lodash");
expect(stderr).toContain("lodash@catalog:stable");
expect(stderr).not.toContain("lodash@catalog:stable");

const { stdout: listOutput } = await workspace.yarn.info();
const dependencies = extractDependencies(listOutput);
Expand Down Expand Up @@ -178,4 +178,43 @@ describe("warnings and recommendations", () => {
const dependencies = extractDependencies(listOutput);
expect(dependencies).includes("react@npm:17.0.0");
});

it("should us default alias group without validation error (default: max)", async () => {
workspace = await createTestWorkspace();

await workspace.writeYarnrc({
catalogs: {
options: {
default: "max",
},
list: {
beta: {
react: "npm:18.0.0",
lodash: "npm:3.0.0",
},
stable: {
react: "npm:17.0.0",
lodash: "npm:2.0.0",
},
},
},
});

await workspace.writeJson("package.json", {
name: "test-workspace",
version: "1.0.0",
private: true,
dependencies: {
react: "catalog:stable",
lodash: "catalog:stable",
},
});

const { stderr } = await workspace.yarn.add("lodash");
expect(stderr).toBe("");

const { stdout: listOutput } = await workspace.yarn.info();
const dependencies = extractDependencies(listOutput);
expect(dependencies).includes("lodash@npm:2.0.0");
});
});
4 changes: 3 additions & 1 deletion sources/utils/default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ export async function fallbackDefaultAliasGroup(
/**
* Get the default alias group from the configuration if it exists
*/
async function getDefaultAliasGroups(workspace: Workspace): Promise<string[]> {
export async function getDefaultAliasGroups(
workspace: Workspace,
): Promise<string[]> {
const config = await configReader.readConfiguration(workspace.project);

if (config.options) {
Expand Down
5 changes: 2 additions & 3 deletions sources/utils/resolution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,8 @@ export async function resolveCatalogDependency(
*/
export async function findAllGroupsWithSpecificDependency(
project: Project,
dependency: Descriptor,
packageName: string,
): Promise<Array<{ groupName: string; version: string }>> {
const dependencyString = structUtils.stringifyIdent(dependency);
const config = await configReader.readConfiguration(project);
const results: Array<{ groupName: string; version: string }> = [];

Expand All @@ -81,7 +80,7 @@ export async function findAllGroupsWithSpecificDependency(
const resolvedVersion = resolveInheritedRange(
config,
groupName,
dependencyString,
packageName,
);

if (resolvedVersion) {
Expand Down
26 changes: 19 additions & 7 deletions sources/utils/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { getInheritanceChain } from "./functions";
import { configReader } from "../configuration";
import { findAllGroupsWithSpecificDependency } from "./resolution";
import { CATALOG_PROTOCOL } from "../constants";
import { getDefaultAliasGroups } from "./default";

/**
* Check if a package can be used with the catalog protocol
Expand All @@ -25,18 +26,29 @@ export async function validateCatalogUsability(
return null;
}

const defaultAliasGroups = await getDefaultAliasGroups(workspace);

// Find all groups that can access this package
const accessibleGroups = (
await findAllGroupsWithSpecificDependency(workspace.project, descriptor)
).map(({ groupName }) => groupName);
const packageName = structUtils.stringifyIdent(descriptor);
const groupsWithDependency = await findAllGroupsWithSpecificDependency(
workspace.project,
packageName,
);
const accessibleGroups = groupsWithDependency.flatMap(({ groupName }) =>
defaultAliasGroups.length === 0 || defaultAliasGroups.includes(groupName)
? [groupName]
: [],
);

// Return null if no applicable groups found
if (accessibleGroups.length === 0) {
return null;
}

// Get validation level for the package
const validationLevel = await getPackageVaidationLevel(workspace, descriptor);
const validationLevel = await getPackageVaidationLevel(
workspace,
packageName,
);

return {
validationLevel,
Expand Down Expand Up @@ -114,10 +126,10 @@ async function getGroupValidationLevel(
*/
async function getPackageVaidationLevel(
workspace: Workspace,
descriptor: Descriptor,
packageName: string,
): Promise<ValidationLevel> {
const accessibleGroups = (
await findAllGroupsWithSpecificDependency(workspace.project, descriptor)
await findAllGroupsWithSpecificDependency(workspace.project, packageName)
).map(({ groupName }) => groupName);

if (accessibleGroups.length === 0) {
Expand Down