From dab17f9e38d2cdb06fbb03c997051d98a5521a87 Mon Sep 17 00:00:00 2001 From: "[ Cassondra ]" Date: Tue, 4 Mar 2025 17:20:51 -0500 Subject: [PATCH 1/3] chore: add basic project constraints --- package.json | 1 + yarn.config.cjs | 184 ++++++++++++++++++++++++++++++++++++++++++++++++ yarn.lock | 10 +++ 3 files changed, 195 insertions(+) create mode 100644 yarn.config.cjs diff --git a/package.json b/package.json index c3f9be37e6..a25d94f8de 100644 --- a/package.json +++ b/package.json @@ -146,6 +146,7 @@ "@web/test-runner-playwright": "^0.11.0", "@web/test-runner-visual-regression": "^0.9.0", "@webcomponents/webcomponentsjs": "^2.8.0", + "@yarnpkg/types": "^4.0.1", "alex": "^11.0.1", "cem-plugin-module-file-extensions": "^0.0.5", "chromatic": "^11.20.0", diff --git a/yarn.config.cjs b/yarn.config.cjs new file mode 100644 index 0000000000..53d3f68a23 --- /dev/null +++ b/yarn.config.cjs @@ -0,0 +1,184 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ +/*! + * Copyright 2025 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +/** @type {import('@yarnpkg/types')} */ +const { defineConfig } = require('@yarnpkg/types'); +const fg = require('fast-glob'); + +/** + * The workspace object used in the constraints function + * @typedef {import('@yarnpkg/types').Yarn.Constraints.Workspace} Workspace + */ + +module.exports = defineConfig({ + async constraints({ Yarn }) { + /** + * Fetch a list of all the component workspaces using a glob pattern + * @type {string[]} components + */ + const components = fg.sync('packages/*', { + cwd: __dirname, + onlyDirectories: true, + }); + + /** + * This function checks the workspace for any local package references + * and ensure that the devDependencies are up-to-date with the latest version + * currently in the project + * @param {Workspace} workspace + * @returns {void} + */ + function validateLocalPackages(workspace) { + // Return early if the workspace does not have any peerDependencies + if (!workspace.manifest.peerDependencies) { + return; + } + + // Start by filtering out the local packages from the external dependencies + const localPackages = Object.keys( + workspace.manifest.peerDependencies + ) + .filter((pkg) => Yarn.workspace({ ident: pkg })) + .map((pkg) => Yarn.workspace({ ident: pkg })); + + // Iterate over the local packages and ensure that the devDependencies are up-to-date + for (const localWorkspace of localPackages) { + const localVersion = localWorkspace.manifest.version; + workspace.set( + `devDependencies.${localWorkspace.manifest.name}`, + localVersion ?? 'workspace:^' + ); + } + } + + /** + * A reusable function to add keywords to ensure workspaces + * include a minimal set of keywords for discoverability + * with additionalKeywords as an optional parameter to add more + * specific keywords that are relevant to the workspace + * @param {string[]} additionalKeywords + * @returns {string[]} + */ + function keywords(additionalKeywords = []) { + return [ + 'design-system', + 'spectrum', + 'adobe', + 'adobe-spectrum', + 'web components', + 'web-components', + 'lit-element', + 'lit-html', + ...additionalKeywords, + ]; + } + + /** + * This function rolls up all the component package.json + * requirements for all workspaces into a single function + * to simplify into a readable set of operations + * @param {Workspace} workspace + * @param {string} folderName + * @returns {void} + */ + function validateComponentPackageJson(workspace, folderName) { + // Only update the homepage if it does not already exist + if (!workspace.manifest.homepage) { + workspace.set( + 'homepage', + `https://opensource.adobe.com/spectrum-web-components/components/${folderName}` + ); + } + + workspace.set('publishConfig.access', 'public'); + workspace.set('keywords', keywords(['component', 'css'])); + workspace.set('main', './src/index.js'); + workspace.set('module', './src/index.js'); + workspace.set('type', 'module'); + } + + /** + * This function rolls up all the package.json requirements + * for all workspaces into a single function to simplify + * the workspace for loop into a readable set of operations + * @param {Workspace} workspace + * @returns {void} + */ + function validatePackageJson(workspace) { + const isRoot = workspace.cwd === '.'; + const isComponent = components.includes(workspace.cwd); + + /** + * -------------- GLOBAL -------------- + * Global configuration for all workspaces + */ + if ( + !workspace.manifest.license || + workspace.manifest.license === '' + ) { + workspace.set('license', 'Apache-2.0'); + } + + workspace.set('author', 'Adobe'); + + workspace.set('repository.type', 'git'); + workspace.set( + 'repository.url', + 'https://github.com/adobe/spectrum-web-components.git' + ); + + // We don't need to set the directory for the root workspace + if (!isRoot) { + workspace.set('repository.directory', workspace.cwd); + } + + workspace.set( + 'bugs.url', + 'https://github.com/adobe/spectrum-web-components/issues' + ); + + /** + * -------------- COMPONENTS -------------- + * Process the components workspaces with component-specific configuration + */ + if (isComponent) { + const folderName = workspace.cwd?.split('/')?.[1]; + validateComponentPackageJson(workspace, folderName); + validateLocalPackages(workspace); + } else { + /** + * -------------- OTHER -------------- + * All other workspaces should have at least the following configuration + */ + if (!workspace.manifest.keywords) { + workspace.set('keywords', keywords()); + } + + if (!workspace.manifest.homepage) { + workspace.set( + 'homepage', + 'https://opensource.adobe.com/spectrum-web-components/' + ); + } + } + } + + /** + * This loop iterates over all the workspaces in the project + * and updates the package.json file with the necessary + */ + for (const workspace of Yarn.workspaces()) { + validatePackageJson(workspace); + } + }, +}); diff --git a/yarn.lock b/yarn.lock index 50109839ab..1005a58772 100644 --- a/yarn.lock +++ b/yarn.lock @@ -244,6 +244,7 @@ __metadata: "@web/test-runner-playwright": "npm:^0.11.0" "@web/test-runner-visual-regression": "npm:^0.9.0" "@webcomponents/webcomponentsjs": "npm:^2.8.0" + "@yarnpkg/types": "npm:^4.0.1" alex: "npm:^11.0.1" cem-plugin-module-file-extensions: "npm:^0.0.5" chromatic: "npm:^11.20.0" @@ -11987,6 +11988,15 @@ __metadata: languageName: node linkType: hard +"@yarnpkg/types@npm:^4.0.1": + version: 4.0.1 + resolution: "@yarnpkg/types@npm:4.0.1" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10c0/90226789475680ba599833571dd76c0718dd5b4c5022481263ef309d6a628f6246671cd6ca86e49c966ddefa7aca6ccef82240dc1476d2cea702ea5bee2a6b72 + languageName: node + linkType: hard + "JSONStream@npm:^1.3.5": version: 1.3.5 resolution: "JSONStream@npm:1.3.5" From 2e792678a4e26e20e704eba8fe9023576bf0ee42 Mon Sep 17 00:00:00 2001 From: castastrophe Date: Wed, 19 Mar 2025 13:16:59 -0400 Subject: [PATCH 2/3] chore: add exception to constraints for clear-button, close-button, and modal --- yarn.config.cjs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/yarn.config.cjs b/yarn.config.cjs index 53d3f68a23..8ea138e3d9 100644 --- a/yarn.config.cjs +++ b/yarn.config.cjs @@ -101,10 +101,19 @@ module.exports = defineConfig({ } workspace.set('publishConfig.access', 'public'); - workspace.set('keywords', keywords(['component', 'css'])); - workspace.set('main', './src/index.js'); - workspace.set('module', './src/index.js'); workspace.set('type', 'module'); + workspace.set('keywords', keywords(['component', 'css'])); + + // A subset of components have a different entry point than the default + if ( + ['clear-button', 'close-button', 'modal'].includes(folderName) + ) { + workspace.set('main', `./src/${folderName}.css.js`); + workspace.set('module', `./src/${folderName}.css.js`); + } else { + workspace.set('main', './src/index.js'); + workspace.set('module', './src/index.js'); + } } /** From 1880c55be7e0a2e205a03c3bdd587ee629f9ec6c Mon Sep 17 00:00:00 2001 From: "[ Cassondra ]" Date: Tue, 25 Mar 2025 12:08:57 -0400 Subject: [PATCH 3/3] chore: update constraints add opacity-checkerboard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: RĂºben Carvalho --- yarn.config.cjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn.config.cjs b/yarn.config.cjs index 8ea138e3d9..100871858b 100644 --- a/yarn.config.cjs +++ b/yarn.config.cjs @@ -106,7 +106,7 @@ module.exports = defineConfig({ // A subset of components have a different entry point than the default if ( - ['clear-button', 'close-button', 'modal'].includes(folderName) + ['clear-button', 'close-button', 'modal', 'opacity-checkerboard'].includes(folderName) ) { workspace.set('main', `./src/${folderName}.css.js`); workspace.set('module', `./src/${folderName}.css.js`);