From b4cd145b574f8ac29bd63bdfb00a3cd5fd62bbee Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 9 Jan 2023 22:52:19 +0100 Subject: [PATCH] cli: added package-exports migration command Signed-off-by: Patrik Oldsberg --- .changeset/long-nails-pump.md | 5 ++ packages/cli/src/commands/index.ts | 7 ++ .../src/commands/migrate/packageExports.ts | 83 +++++++++++++++++++ packages/cli/src/lib/monorepo/PackageGraph.ts | 4 + 4 files changed, 99 insertions(+) create mode 100644 .changeset/long-nails-pump.md create mode 100644 packages/cli/src/commands/migrate/packageExports.ts diff --git a/.changeset/long-nails-pump.md b/.changeset/long-nails-pump.md new file mode 100644 index 0000000000..d9eefc0249 --- /dev/null +++ b/.changeset/long-nails-pump.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Added a new `migrate package-exports` command that synchronizes package exports fields in all `package.json`s. diff --git a/packages/cli/src/commands/index.ts b/packages/cli/src/commands/index.ts index 628e46df85..2fdd2442d4 100644 --- a/packages/cli/src/commands/index.ts +++ b/packages/cli/src/commands/index.ts @@ -191,6 +191,13 @@ export function registerMigrateCommand(program: Command) { lazy(() => import('./migrate/packageScripts').then(m => m.command)), ); + command + .command('package-exports') + .description('Synchronize package sub-path export definitions') + .action( + lazy(() => import('./migrate/packageExports').then(m => m.command)), + ); + command .command('package-lint-configs') .description( diff --git a/packages/cli/src/commands/migrate/packageExports.ts b/packages/cli/src/commands/migrate/packageExports.ts new file mode 100644 index 0000000000..3a59c02375 --- /dev/null +++ b/packages/cli/src/commands/migrate/packageExports.ts @@ -0,0 +1,83 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed 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 CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import fs from 'fs-extra'; +import { resolve as resolvePath } from 'path'; +import { PackageGraph } from '../../lib/monorepo'; + +function trimRelative(path: string): string { + if (path.startsWith('./')) { + return path.slice(2); + } + return path; +} + +export async function command() { + const packages = await PackageGraph.listTargetPackages(); + + await Promise.all( + packages.map(async ({ dir, packageJson }) => { + const { exports: exp } = packageJson; + if (!exp || typeof exp !== 'object' || Array.isArray(exp)) { + return; + } + + const existingTypesVersions = JSON.stringify(packageJson.typesVersions); + + const typeEntries: Record = {}; + + for (const [path, value] of Object.entries(exp)) { + const newPath = path === '.' ? '*' : trimRelative(path); + + if (typeof value === 'string') { + typeEntries[newPath] = [trimRelative(value)]; + } else if ( + value && + typeof value === 'object' && + !Array.isArray(value) + ) { + if (typeof value.types === 'string') { + typeEntries[newPath] = [trimRelative(value.types)]; + } else if (typeof value.default === 'string') { + typeEntries[newPath] = [trimRelative(value.default)]; + } + } + } + + const typesVersions = { '*': typeEntries }; + + if (existingTypesVersions !== JSON.stringify(typesVersions)) { + console.log(`Synchronizing exports in ${packageJson.name}`); + const newPkgEntries = Object.entries(packageJson).filter( + ([name]) => name !== 'typesVersions', + ); + newPkgEntries.splice( + newPkgEntries.findIndex(([name]) => name === 'exports') + 1, + 0, + ['typesVersions', typesVersions], + ); + + await fs.writeJson( + resolvePath(dir, 'package.json'), + Object.fromEntries(newPkgEntries), + { + spaces: 2, + }, + ); + } + }), + ); +} diff --git a/packages/cli/src/lib/monorepo/PackageGraph.ts b/packages/cli/src/lib/monorepo/PackageGraph.ts index a1fc95e669..d34ede41ae 100644 --- a/packages/cli/src/lib/monorepo/PackageGraph.ts +++ b/packages/cli/src/lib/monorepo/PackageGraph.ts @@ -20,6 +20,7 @@ import { paths } from '../paths'; import { PackageRole } from '../role'; import { listChangedFiles, readFileAtRef } from '../git'; import { Lockfile } from '../versioning'; +import { JsonValue } from '@backstage/types'; type PackageJSON = Package['packageJson']; @@ -34,6 +35,9 @@ export interface ExtendedPackageJSON extends PackageJSON { backstage?: { role?: PackageRole; }; + + exports?: JsonValue; + typesVersions?: Record>; } export type ExtendedPackage = {