From de4f500c22a3454f95ca5fc13c9afd1e99730295 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 7 Jan 2022 13:10:23 +0100 Subject: [PATCH] cli: migrate packager to use PackageGraph Signed-off-by: Patrik Oldsberg --- packages/cli/src/lib/monorepo/PackageGraph.ts | 16 +++- packages/cli/src/lib/packager/index.ts | 76 +++++-------------- 2 files changed, 35 insertions(+), 57 deletions(-) diff --git a/packages/cli/src/lib/monorepo/PackageGraph.ts b/packages/cli/src/lib/monorepo/PackageGraph.ts index 557b942405..9860b92ef6 100644 --- a/packages/cli/src/lib/monorepo/PackageGraph.ts +++ b/packages/cli/src/lib/monorepo/PackageGraph.ts @@ -16,13 +16,24 @@ import { Package } from '@manypkg/get-packages'; +type PackageJSON = Package['packageJson']; + +export interface ExtendedPackageJSON extends PackageJSON { + scripts?: { + [key: string]: string; + }; + // The `bundled` field is a field known within Backstage, it means + // that the package bundles all of its dependencies in its build output. + bundled?: boolean; +} + export type PackageGraphNode = { /** The name of the package */ name: string; /** The directory of the package */ dir: string; /** The package data of the package itself */ - packageJson: Package['packageJson']; + packageJson: ExtendedPackageJSON; /** All direct local dependencies of the package */ allLocalDependencies: Map; /** All direct local dependencies that will be present in the published package */ @@ -50,8 +61,9 @@ export class PackageGraph extends Map { } graph.set(name, { - ...pkg, name, + dir: pkg.dir, + packageJson: pkg.packageJson as ExtendedPackageJSON, allLocalDependencies: new Map(), publishedLocalDependencies: new Map(), localDependencies: new Map(), diff --git a/packages/cli/src/lib/packager/index.ts b/packages/cli/src/lib/packager/index.ts index 4faf904177..c35e2587b9 100644 --- a/packages/cli/src/lib/packager/index.ts +++ b/packages/cli/src/lib/packager/index.ts @@ -29,6 +29,8 @@ import { dependencies as cliDependencies, devDependencies as cliDevDependencies, } from '../../../package.json'; +import { getPackages } from '@manypkg/get-packages'; +import { PackageGraph, PackageGraphNode } from '../monorepo'; // These packages aren't safe to pack in parallel since the CLI depends on them const UNSAFE_PACKAGES = [ @@ -36,14 +38,6 @@ const UNSAFE_PACKAGES = [ ...Object.keys(cliDevDependencies), ]; -type LernaPackage = { - name: string; - private: boolean; - location: string; - scripts: Record; - get(key: string): any; -}; - type FileEntry = | string | { @@ -102,7 +96,17 @@ export async function createDistWorkspace( options.targetDir ?? (await fs.mkdtemp(resolvePath(tmpdir(), 'dist-workspace'))); - const targets = await findTargetPackages(packageNames); + const { packages } = await getPackages(paths.targetDir); + const packageGraph = PackageGraph.fromPackages(packages); + const targetNames = packageGraph.collectPackageNames(packageNames, node => { + // Don't include dependencies of packages that are marked as bundled + if (node.packageJson.bundled) { + return undefined; + } + + return node.publishedLocalDependencies.keys(); + }); + const targets = Array.from(targetNames).map(name => packageGraph.get(name)!); if (options.buildDependencies) { const exclude = options.buildExcludes ?? []; @@ -133,7 +137,7 @@ export async function createDistWorkspace( if (options.skeleton) { const skeletonFiles = targets.map(target => { - const dir = relativePath(paths.targetRoot, target.location); + const dir = relativePath(paths.targetRoot, target.dir); return joinPath(dir, 'package.json'); }); @@ -154,21 +158,21 @@ export async function createDistWorkspace( async function moveToDistWorkspace( workspaceDir: string, - localPackages: LernaPackage[], + localPackages: PackageGraphNode[], ): Promise { - async function pack(target: LernaPackage, archive: string) { + async function pack(target: PackageGraphNode, archive: string) { console.log(`Repacking ${target.name} into dist workspace`); const archivePath = resolvePath(workspaceDir, archive); await run('yarn', ['pack', '--filename', archivePath], { - cwd: target.location, + cwd: target.dir, }); // TODO(Rugvip): yarn pack doesn't call postpack, once the bug is fixed this can be removed - if (target.scripts.postpack) { - await run('yarn', ['postpack'], { cwd: target.location }); + if (target.packageJson?.scripts?.postpack) { + await run('yarn', ['postpack'], { cwd: target.dir }); } - const outputDir = relativePath(paths.targetRoot, target.location); + const outputDir = relativePath(paths.targetRoot, target.dir); const absoluteOutputPath = resolvePath(workspaceDir, outputDir); await fs.ensureDir(absoluteOutputPath); @@ -181,7 +185,7 @@ async function moveToDistWorkspace( // We remove the dependencies from package.json of packages that are marked // as bundled, so that yarn doesn't try to install them. - if (target.get('bundled')) { + if (target.packageJson.bundled) { const pkgJson = await fs.readJson( resolvePath(absoluteOutputPath, 'package.json'), ); @@ -220,41 +224,3 @@ async function moveToDistWorkspace( ), ); } - -async function findTargetPackages(pkgNames: string[]): Promise { - const { Project } = require('@lerna/project'); - const { PackageGraph } = require('@lerna/package-graph'); - - const project = new Project(paths.targetDir); - const packages = await project.getPackages(); - const graph = new PackageGraph(packages); - - const targets = new Map(); - const searchNames = pkgNames.slice(); - - while (searchNames.length) { - const name = searchNames.pop()!; - - if (targets.has(name)) { - continue; - } - - const node = graph.get(name); - if (!node) { - throw new Error(`Package '${name}' not found`); - } - - // Don't include dependencies of packages that are marked as bundled - if (!node.pkg.get('bundled')) { - const pkgDeps = Object.keys(node.pkg.dependencies ?? {}); - const localDeps: string[] = Array.from(node.localDependencies.keys()); - const filteredDeps = localDeps.filter(dep => pkgDeps.includes(dep)); - - searchNames.push(...filteredDeps); - } - - targets.set(name, node.pkg); - } - - return Array.from(targets.values()); -}