From c36c9781daafc529a45f0676346c2ccb0652d978 Mon Sep 17 00:00:00 2001 From: Miorel-Lucian Palii Date: Sun, 22 Sep 2024 16:15:17 -0700 Subject: [PATCH] Have some fun with Yarn constraints I recently learned about Yarn constraints (https://yarnpkg.com/features/constraints), so I've been yearning for a chance to try them. --- package.json | 1 + yarn.config.cjs | 52 +++++++++++++++++++++++++++++++++++++++++++++++-- yarn.lock | 12 +++++++++++- 3 files changed, 62 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 212862d4..a8eafa73 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ }, "devDependencies": { "@code-chronicles/eslint-config": "workspace:*", + "@yarnpkg/types": "4.0.0", "eslint": "9.11.0", "husky": "9.1.6", "lint-staged": "15.2.10", diff --git a/yarn.config.cjs b/yarn.config.cjs index 87010d06..b68732b7 100644 --- a/yarn.config.cjs +++ b/yarn.config.cjs @@ -1,7 +1,55 @@ -module.exports = { +const { defineConfig } = require("@yarnpkg/types"); + +module.exports = defineConfig({ async constraints({ Yarn }) { + const rootWorkspace = Yarn.workspace({ cwd: "." }); + if (rootWorkspace == null) { + Yarn.workspace().error("Didn't find a root workspace?!"); + return; + } + + // Use ESM everywhere. for (const workspace of Yarn.workspaces()) { workspace.set("type", "module"); } + + // Set a consistent repository for all workspaces. + if (rootWorkspace.manifest.repository == null) { + rootWorkspace.error("Missing repository specification!"); + } + for (const workspace of Yarn.workspaces()) { + if (workspace.cwd !== ".") { + workspace.set("repository.directory", workspace.cwd); + workspace.set( + "repository.type", + rootWorkspace.manifest.repository.type, + ); + workspace.set("repository.url", rootWorkspace.manifest.repository.url); + } else { + workspace.unset("repository.directory"); + } + } + + // Expect each workspace to either have a license or be private. + for (const workspace of Yarn.workspaces()) { + if (workspace.manifest.license == null && !workspace.manifest.private) { + // Don't default since we want a human to make the call. + workspace.error("Missing license for non-private workspace!"); + } + } + + // Expect each workspace to specify a version, except for the root. + for (const workspace of Yarn.workspaces()) { + if (workspace.cwd !== ".") { + workspace.set("version", workspace.manifest.version ?? "0.0.1"); + } else { + workspace.unset("version"); + } + } + + // Explicitly specify whether the workspace is private or not. + for (const workspace of Yarn.workspaces()) { + workspace.set("private", !!workspace.manifest.private); + } }, -}; +}); diff --git a/yarn.lock b/yarn.lock index 2c6a6f61..e41d8375 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2142,6 +2142,15 @@ __metadata: languageName: node linkType: hard +"@yarnpkg/types@npm:4.0.0": + version: 4.0.0 + resolution: "@yarnpkg/types@npm:4.0.0" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10c0/41f67a4aa5c414c1e228f51453451fa15e0dd70c5cf2b1ae1ca142a3f018f25e4a37e60372cd0f5970c755e1804a2e31e208bff427add1cf13f899b0b9adc1e0 + languageName: node + linkType: hard + "abbrev@npm:^2.0.0": version: 2.0.0 resolution: "abbrev@npm:2.0.0" @@ -6989,6 +6998,7 @@ __metadata: resolution: "root-workspace-0b6124@workspace:." dependencies: "@code-chronicles/eslint-config": "workspace:*" + "@yarnpkg/types": "npm:4.0.0" eslint: "npm:9.11.0" husky: "npm:9.1.6" lint-staged: "npm:15.2.10" @@ -7682,7 +7692,7 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.6.2, tslib@npm:^2.6.3": +"tslib@npm:^2.4.0, tslib@npm:^2.6.2, tslib@npm:^2.6.3": version: 2.7.0 resolution: "tslib@npm:2.7.0" checksum: 10c0/469e1d5bf1af585742128827000711efa61010b699cb040ab1800bcd3ccdd37f63ec30642c9e07c4439c1db6e46345582614275daca3e0f4abae29b0083f04a6