Revert most changes
Signed-off-by: Gabriel Dugny <gabriel.dugny@believe.com>
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
---
|
||||
'@backstage/cli-common': patch
|
||||
'@backstage/create-app': patch
|
||||
'@backstage/cli-node': patch
|
||||
'@backstage/cli': patch
|
||||
|
||||
@@ -23,9 +23,6 @@ export class ExitCodeError extends CustomErrorBase {
|
||||
// @public
|
||||
export function findPaths(searchDir: string): Paths;
|
||||
|
||||
// @public
|
||||
export function getWorkspacesPatterns(pkgJson: unknown): string[];
|
||||
|
||||
// @public
|
||||
export function isChildPath(base: string, path: string): boolean;
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
*/
|
||||
|
||||
export { findPaths, BACKSTAGE_JSON } from './paths';
|
||||
export { getWorkspacesPatterns } from './workspaces';
|
||||
export { isChildPath } from './isChildPath';
|
||||
export type { Paths, ResolveFunc } from './paths';
|
||||
export { bootstrapEnvProxyAgents } from './proxyBootstrap';
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
import fs from 'node:fs';
|
||||
import { dirname, resolve as resolvePath } from 'node:path';
|
||||
import { getWorkspacesPatterns } from './workspaces';
|
||||
|
||||
/**
|
||||
* A function that takes a set of path fragments and resolves them into a
|
||||
@@ -142,7 +141,7 @@ export function findPaths(searchDir: string): Paths {
|
||||
try {
|
||||
const content = fs.readFileSync(path, 'utf8');
|
||||
const data = JSON.parse(content);
|
||||
return getWorkspacesPatterns(data).length > 0;
|
||||
return Boolean(data.workspaces);
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
`Failed to parse package.json file while searching for root, ${error}`,
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright 2026 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 { getWorkspacesPatterns } from './workspaces';
|
||||
|
||||
describe('getWorkspacesPatterns', () => {
|
||||
it('returns empty array when pkgJson has no workspaces key', () => {
|
||||
expect(getWorkspacesPatterns({ name: 'pkg' })).toEqual([]);
|
||||
});
|
||||
|
||||
it('returns patterns when workspaces is array form', () => {
|
||||
const patterns = ['packages/*', 'apps/*'];
|
||||
expect(getWorkspacesPatterns({ workspaces: patterns })).toEqual(patterns);
|
||||
});
|
||||
|
||||
it('returns patterns when workspaces is object form with packages', () => {
|
||||
const patterns = ['packages/*'];
|
||||
expect(
|
||||
getWorkspacesPatterns({ workspaces: { packages: patterns } }),
|
||||
).toEqual(patterns);
|
||||
});
|
||||
|
||||
it('returns empty array when workspaces is object without packages array', () => {
|
||||
expect(getWorkspacesPatterns({ workspaces: {} })).toEqual([]);
|
||||
expect(getWorkspacesPatterns({ workspaces: { noMatch: [] } })).toEqual([]);
|
||||
});
|
||||
|
||||
it('throws when pkgJson is not an object', () => {
|
||||
expect(() => getWorkspacesPatterns(null)).toThrow(
|
||||
'pkgJson must be an object',
|
||||
);
|
||||
expect(() => getWorkspacesPatterns('string')).toThrow(
|
||||
'pkgJson must be an object',
|
||||
);
|
||||
expect(() => getWorkspacesPatterns(42)).toThrow(
|
||||
'pkgJson must be an object',
|
||||
);
|
||||
});
|
||||
|
||||
it('throws when workspaces array contains non-strings', () => {
|
||||
expect(() => getWorkspacesPatterns({ workspaces: ['a', 1, 'b'] })).toThrow(
|
||||
'must be an array of strings',
|
||||
);
|
||||
expect(() => getWorkspacesPatterns({ workspaces: [null] })).toThrow(
|
||||
'must be an array of strings',
|
||||
);
|
||||
});
|
||||
|
||||
it('throws when workspaces.packages contains non-strings', () => {
|
||||
expect(() =>
|
||||
getWorkspacesPatterns({
|
||||
workspaces: { packages: ['a', 1] },
|
||||
}),
|
||||
).toThrow('must be an array of strings');
|
||||
});
|
||||
});
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Copyright 2026 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.
|
||||
*/
|
||||
|
||||
function assertStringArray(
|
||||
value: unknown,
|
||||
field: string,
|
||||
): asserts value is string[] {
|
||||
if (!Array.isArray(value)) {
|
||||
throw new Error(`${field} must be an array`);
|
||||
}
|
||||
if (!value.every((item): item is string => typeof item === 'string')) {
|
||||
throw new Error(`${field} must be an array of strings`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the workspaces patterns from a package.json object.
|
||||
*
|
||||
* Supports both the array form (`"workspaces": ["packages/*"]`) and the object
|
||||
* form (`"workspaces": { "packages": ["packages/*"] }`) from npm/yarn.
|
||||
*
|
||||
* @param pkgJson - The package.json object. Type as `unknown` so callers must pass parsed JSON; an object type check is performed.
|
||||
* @returns The workspaces patterns (globs not resolved). Empty array if none.
|
||||
* @throws Error if `pkgJson` is not an object or workspaces/packages contain non-strings.
|
||||
* @public
|
||||
*/
|
||||
export function getWorkspacesPatterns(pkgJson: unknown): string[] {
|
||||
if (typeof pkgJson !== 'object' || pkgJson === null) {
|
||||
throw new Error('pkgJson must be an object');
|
||||
}
|
||||
if (!('workspaces' in pkgJson)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const workspaces = pkgJson.workspaces;
|
||||
if (Array.isArray(workspaces)) {
|
||||
assertStringArray(workspaces, 'pkgJson.workspaces');
|
||||
return workspaces;
|
||||
}
|
||||
if (
|
||||
typeof workspaces === 'object' &&
|
||||
workspaces !== null &&
|
||||
'packages' in workspaces &&
|
||||
Array.isArray(workspaces.packages)
|
||||
) {
|
||||
assertStringArray(workspaces.packages, 'pkgJson.workspaces.packages');
|
||||
return workspaces.packages;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
@@ -14,12 +14,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { getWorkspacesPatterns } from '@backstage/cli-common';
|
||||
import { paths } from '../paths';
|
||||
import fs from 'fs-extra';
|
||||
|
||||
/**
|
||||
* Returns try if the current project is a monorepo.
|
||||
* Returns true if the current project is a monorepo.
|
||||
*
|
||||
* Uses a simple presence check on the `workspaces` field. Empty or invalid
|
||||
* workspace config is treated as a monorepo; we do not validate patterns.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
@@ -27,7 +29,7 @@ export async function isMonoRepo(): Promise<boolean> {
|
||||
const rootPackageJsonPath = paths.resolveTargetRoot('package.json');
|
||||
try {
|
||||
const pkg = await fs.readJson(rootPackageJsonPath);
|
||||
return getWorkspacesPatterns(pkg).length > 0;
|
||||
return Boolean(pkg?.workspaces);
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -43,19 +43,19 @@ describe('PackageManager', () => {
|
||||
expect(mockYarnCreate).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should detect via root package.json workspaces with legacy workspaces.packages field', async () => {
|
||||
it('should detect via root package.json workspaces', async () => {
|
||||
mockDir.setContent({
|
||||
'package.json': JSON.stringify({
|
||||
name: 'foo',
|
||||
workspaces: {
|
||||
packages: ['packages/*'],
|
||||
packages: [],
|
||||
},
|
||||
}),
|
||||
});
|
||||
await detectPackageManager();
|
||||
expect(mockYarnCreate).toHaveBeenCalled();
|
||||
});
|
||||
it('should detect via root package.json workspaces', async () => {
|
||||
it('should detect via root package.json workspaces (array form)', async () => {
|
||||
mockDir.setContent({
|
||||
'package.json': JSON.stringify({
|
||||
name: 'foo',
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
import { Yarn } from './yarn';
|
||||
import { Lockfile } from './Lockfile';
|
||||
import { paths } from '../paths';
|
||||
import { getWorkspacesPatterns, RunOptions } from '@backstage/cli-common';
|
||||
import { RunOptions } from '@backstage/cli-common';
|
||||
import fs from 'fs-extra';
|
||||
|
||||
/**
|
||||
@@ -101,7 +101,7 @@ export async function detectPackageManager(): Promise<PackageManager> {
|
||||
const packageJson = await fs.readJson(
|
||||
paths.resolveTargetRoot('package.json'),
|
||||
);
|
||||
if (getWorkspacesPatterns(packageJson).length > 0) {
|
||||
if (packageJson.workspaces) {
|
||||
// technically this could be NPM as well
|
||||
return await Yarn.create();
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ import { YarnVersion } from './types';
|
||||
import fs from 'fs-extra';
|
||||
import { paths } from '../../paths';
|
||||
import { run, runOutput, RunOptions } from '@backstage/cli-common';
|
||||
import { getWorkspacesPatterns } from '@backstage/cli-common';
|
||||
|
||||
export class Yarn implements PackageManager {
|
||||
constructor(private readonly yarnVersion: YarnVersion) {}
|
||||
@@ -51,7 +50,10 @@ export class Yarn implements PackageManager {
|
||||
const rootPackageJsonPath = paths.resolveTargetRoot('package.json');
|
||||
try {
|
||||
const pkg = await fs.readJson(rootPackageJsonPath);
|
||||
return getWorkspacesPatterns(pkg);
|
||||
const workspaces = pkg?.workspaces;
|
||||
return Array.isArray(workspaces)
|
||||
? workspaces
|
||||
: workspaces?.packages ?? [];
|
||||
} catch (error) {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ const crypto = require('node:crypto');
|
||||
const glob = require('node:util').promisify(require('glob'));
|
||||
const { version } = require('../package.json');
|
||||
const paths = require('@backstage/cli-common').findPaths(process.cwd());
|
||||
const { getWorkspacesPatterns } = require('@backstage/cli-common');
|
||||
const {
|
||||
getJestEnvironment,
|
||||
getJestMajorVersion,
|
||||
@@ -337,10 +336,11 @@ async function getRootConfig() {
|
||||
rejectFrontendNetworkRequests,
|
||||
};
|
||||
|
||||
const workspacePatterns = getWorkspacesPatterns(rootPkgJson);
|
||||
const ws = rootPkgJson.workspaces;
|
||||
const workspacePatterns = Array.isArray(ws) ? ws : ws?.packages;
|
||||
|
||||
// Check if we're running within a specific monorepo package. In that case just get the single project config.
|
||||
if (workspacePatterns.length === 0 || paths.targetRoot !== paths.targetDir) {
|
||||
if (!workspacePatterns || paths.targetRoot !== paths.targetDir) {
|
||||
return getProjectConfig(
|
||||
paths.targetDir,
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user