yarn.config.cjs (122 lines of code) (raw):

// /** @type {import('@yarnpkg/types')} */ // const { defineConfig } = require('@yarnpkg/types'); const defineConfig = config => config; module.exports = defineConfig({ async constraints({ Yarn }) { const root = Yarn.workspace({ cwd: '.' }); for (const workspace of Yarn.workspaces()) { const depsToWorkspace = Yarn.dependencies({ ident: workspace.ident }); if (!workspace.cwd.startsWith('packages/')) { // workspace is not a published package (example or root) // ...it should be private workspace.set('private', true); // ...there should be no dependencies to it for (const dep of depsToWorkspace) { dep.delete(); } // done with this workspace continue; } // workspace is a published package // make sure all deps to this workspace use the correct version for (const dep of depsToWorkspace) { if (dep.workspace.cwd.startsWith('examples/')) { // example apps should always use the workspace version dep.update('workspace:*'); } else if (dep.type === 'peerDependencies') { // peer dependencies should use a GT & LT range // example: ">=0.1.4 <=0.3.x" where 0.3.x is the next breaking version const [minVersion] = dep.range.match(/^>=\d+\.\d+\.\d+/) || []; if (!minVersion) { dep.error(`Expected peer dependency to use a min version`); } // TODO maybe automatically set the max version to the next breaking version // dep.workspace.set(['peerDependencies', dep.ident], `${minVersion} <=${workspace.pkg.version}`); // peer dependencies should also have a dev dependency to the workspace dep.workspace.set(['devDependencies', dep.ident], 'workspace:*'); } else if (dep.type === 'devDependencies') { dep.update('workspace:*'); } else if (dep.type === 'dependencies') { // there should be no regular deps between packages. dep.delete(); } } // package.json invariants workspace.set('type', 'module'); if (workspace.cwd === 'packages/react') { workspace.set('files', ['./index.*', './server.*']); workspace.set('scripts.prepack', 'yarn build && yarn bundle && cp dist/* .'); workspace.set('scripts.postpack', 'rm server.* & rm index.*'); workspace.set( 'exports', buildExports({ '.': 'index', './server': 'server', }), ); workspace.set('publishConfig', { registry: 'https://registry.npmjs.org/', access: 'public', main: 'index.cjs', module: 'index.mjs', types: 'index.d.ts', exports: { '.': { import: './index.mjs', require: './index.cjs', types: './index.d.ts', }, './server': { import: './server.mjs', require: './server.cjs', types: './server.d.ts', }, }, }); } else { workspace.set('files', ['dist/index.*']); workspace.set('scripts.prepack', 'yarn build && yarn bundle'); workspace.set('exports', buildExports({ '.': 'index' })); workspace.set('publishConfig', { registry: 'https://registry.npmjs.org/', access: 'public', exports: distExports({ '.': 'index' }), main: 'dist/index.cjs', module: 'dist/index.mjs', types: 'dist/index.d.ts', }); } if (workspace.cwd === 'packages/sdk') { workspace.set('scripts.bundle', 'rollup -c && api-extractor run'); } else { workspace.set('scripts.bundle', 'rollup -c && ../../validate-api.sh'); } workspace.set('scripts.build', 'tsc'); workspace.set('scripts.clean', 'rm -rf {build,dist}'); workspace.unset('main'); workspace.unset('module'); workspace.unset('types'); // dev deps that should all share the same version (from root package.json) for (const id of ['rollup', 'typescript']) { workspace.set(['devDependencies', id], getRootVersion(id)); } } function getRootVersion(id) { const version = root.pkg.dependencies.get(id)?.version; if (!version) { root.error(`Expected dependency on ${id}.`); } return version; } }, }); function buildExports(map) { return Object.fromEntries( Object.entries(map).map(([key, value]) => { if (typeof value === 'string') { value = { import: `./build/${value}.js`, types: `./build/${value}.d.ts`, }; } return [key, value]; }), ); } function distExports(map) { return Object.fromEntries( Object.entries(map).map(([key, value]) => { if (typeof value === 'string') { value = { import: `./dist/${value}.mjs`, require: `./dist/${value}.cjs`, types: `./dist/${value}.d.ts`, }; } return [key, value]; }), ); }