cli-node: refactor role utils into PackageRoles + document, move stuff back
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -21,3 +21,4 @@
|
||||
*/
|
||||
|
||||
export * from './git';
|
||||
export * from './roles';
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
import path from 'path';
|
||||
import { getPackages, Package } from '@manypkg/get-packages';
|
||||
import { paths } from '../paths';
|
||||
import { PackageRole } from '../role';
|
||||
import { PackageRole } from '../roles';
|
||||
import { GitUtils } from '../git';
|
||||
import { Lockfile } from './Lockfile';
|
||||
import { JsonValue } from '@backstage/types';
|
||||
|
||||
@@ -1,188 +0,0 @@
|
||||
/*
|
||||
* Copyright 2022 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 { z } from 'zod';
|
||||
import fs from 'fs-extra';
|
||||
import { OptionValues } from 'commander';
|
||||
import { paths } from '../paths';
|
||||
import { PackageRole, PackageRoleInfo } from './types';
|
||||
|
||||
const packageRoleInfos: PackageRoleInfo[] = [
|
||||
{
|
||||
role: 'frontend',
|
||||
platform: 'web',
|
||||
output: ['bundle'],
|
||||
},
|
||||
{
|
||||
role: 'backend',
|
||||
platform: 'node',
|
||||
output: ['bundle'],
|
||||
},
|
||||
{
|
||||
role: 'cli',
|
||||
platform: 'node',
|
||||
output: ['cjs'],
|
||||
},
|
||||
{
|
||||
role: 'web-library',
|
||||
platform: 'web',
|
||||
output: ['types', 'esm'],
|
||||
},
|
||||
{
|
||||
role: 'node-library',
|
||||
platform: 'node',
|
||||
output: ['types', 'cjs'],
|
||||
},
|
||||
{
|
||||
role: 'common-library',
|
||||
platform: 'common',
|
||||
output: ['types', 'esm', 'cjs'],
|
||||
},
|
||||
{
|
||||
role: 'frontend-plugin',
|
||||
platform: 'web',
|
||||
output: ['types', 'esm'],
|
||||
},
|
||||
{
|
||||
role: 'frontend-plugin-module',
|
||||
platform: 'web',
|
||||
output: ['types', 'esm'],
|
||||
},
|
||||
{
|
||||
role: 'backend-plugin',
|
||||
platform: 'node',
|
||||
output: ['types', 'cjs'],
|
||||
},
|
||||
{
|
||||
role: 'backend-plugin-module',
|
||||
platform: 'node',
|
||||
output: ['types', 'cjs'],
|
||||
},
|
||||
];
|
||||
|
||||
export function getRoleInfo(role: string): PackageRoleInfo {
|
||||
const roleInfo = packageRoleInfos.find(r => r.role === role);
|
||||
if (!roleInfo) {
|
||||
throw new Error(`Unknown package role '${role}'`);
|
||||
}
|
||||
return roleInfo;
|
||||
}
|
||||
|
||||
const readSchema = z.object({
|
||||
name: z.string().optional(),
|
||||
backstage: z
|
||||
.object({
|
||||
role: z.string().optional(),
|
||||
})
|
||||
.optional(),
|
||||
});
|
||||
|
||||
export function getRoleFromPackage(pkgJson: unknown): PackageRole | undefined {
|
||||
const pkg = readSchema.parse(pkgJson);
|
||||
|
||||
// If there's an explicit role, use that.
|
||||
if (pkg.backstage) {
|
||||
const { role } = pkg.backstage;
|
||||
if (!role) {
|
||||
throw new Error(
|
||||
`Package ${pkg.name} must specify a role in the "backstage" field`,
|
||||
);
|
||||
}
|
||||
|
||||
return getRoleInfo(role).role;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export async function findRoleFromCommand(
|
||||
opts: OptionValues,
|
||||
): Promise<PackageRole> {
|
||||
if (opts.role) {
|
||||
return getRoleInfo(opts.role)?.role;
|
||||
}
|
||||
|
||||
const pkg = await fs.readJson(paths.resolveTarget('package.json'));
|
||||
const info = getRoleFromPackage(pkg);
|
||||
if (!info) {
|
||||
throw new Error(`Target package must have 'backstage.role' set`);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
const detectionSchema = z.object({
|
||||
name: z.string().optional(),
|
||||
scripts: z
|
||||
.object({
|
||||
start: z.string().optional(),
|
||||
build: z.string().optional(),
|
||||
})
|
||||
.optional(),
|
||||
publishConfig: z
|
||||
.object({
|
||||
main: z.string().optional(),
|
||||
types: z.string().optional(),
|
||||
module: z.string().optional(),
|
||||
})
|
||||
.optional(),
|
||||
main: z.string().optional(),
|
||||
types: z.string().optional(),
|
||||
module: z.string().optional(),
|
||||
});
|
||||
|
||||
export function detectRoleFromPackage(
|
||||
pkgJson: unknown,
|
||||
): PackageRole | undefined {
|
||||
const pkg = detectionSchema.parse(pkgJson);
|
||||
|
||||
if (pkg.scripts?.start?.includes('app:serve')) {
|
||||
return 'frontend';
|
||||
}
|
||||
if (pkg.scripts?.build?.includes('backend:bundle')) {
|
||||
return 'backend';
|
||||
}
|
||||
if (pkg.name?.includes('plugin-') && pkg.name?.includes('-backend-module-')) {
|
||||
return 'backend-plugin-module';
|
||||
}
|
||||
if (pkg.name?.includes('plugin-') && pkg.name?.includes('-module-')) {
|
||||
return 'frontend-plugin-module';
|
||||
}
|
||||
if (pkg.scripts?.start?.includes('plugin:serve')) {
|
||||
return 'frontend-plugin';
|
||||
}
|
||||
if (pkg.scripts?.start?.includes('backend:dev')) {
|
||||
return 'backend-plugin';
|
||||
}
|
||||
|
||||
const mainEntry = pkg.publishConfig?.main || pkg.main;
|
||||
const moduleEntry = pkg.publishConfig?.module || pkg.module;
|
||||
const typesEntry = pkg.publishConfig?.types || pkg.types;
|
||||
if (typesEntry) {
|
||||
if (mainEntry && moduleEntry) {
|
||||
return 'common-library';
|
||||
}
|
||||
if (moduleEntry || mainEntry?.endsWith('.esm.js')) {
|
||||
return 'web-library';
|
||||
}
|
||||
if (mainEntry) {
|
||||
return 'node-library';
|
||||
}
|
||||
} else if (mainEntry) {
|
||||
return 'cli';
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
+17
-62
@@ -14,30 +14,23 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import mockFs from 'mock-fs';
|
||||
import { Command } from 'commander';
|
||||
import {
|
||||
getRoleInfo,
|
||||
getRoleFromPackage,
|
||||
findRoleFromCommand,
|
||||
detectRoleFromPackage,
|
||||
} from './PackageRoles';
|
||||
import { PackageRoles } from './PackageRoles';
|
||||
|
||||
describe('getRoleInfo', () => {
|
||||
it('provides role info by role', () => {
|
||||
expect(getRoleInfo('web-library')).toEqual({
|
||||
expect(PackageRoles.getRoleInfo('web-library')).toEqual({
|
||||
role: 'web-library',
|
||||
platform: 'web',
|
||||
output: ['types', 'esm'],
|
||||
});
|
||||
|
||||
expect(getRoleInfo('frontend')).toEqual({
|
||||
expect(PackageRoles.getRoleInfo('frontend')).toEqual({
|
||||
role: 'frontend',
|
||||
platform: 'web',
|
||||
output: ['bundle'],
|
||||
});
|
||||
|
||||
expect(() => getRoleInfo('invalid')).toThrow(
|
||||
expect(() => PackageRoles.getRoleInfo('invalid')).toThrow(
|
||||
`Unknown package role 'invalid'`,
|
||||
);
|
||||
});
|
||||
@@ -46,7 +39,7 @@ describe('getRoleInfo', () => {
|
||||
describe('getRoleFromPackage', () => {
|
||||
it('reads explicit package roles', () => {
|
||||
expect(
|
||||
getRoleFromPackage({
|
||||
PackageRoles.getRoleFromPackage({
|
||||
backstage: {
|
||||
role: 'web-library',
|
||||
},
|
||||
@@ -54,7 +47,7 @@ describe('getRoleFromPackage', () => {
|
||||
).toEqual('web-library');
|
||||
|
||||
expect(
|
||||
getRoleFromPackage({
|
||||
PackageRoles.getRoleFromPackage({
|
||||
backstage: {
|
||||
role: 'frontend',
|
||||
},
|
||||
@@ -62,14 +55,14 @@ describe('getRoleFromPackage', () => {
|
||||
).toEqual('frontend');
|
||||
|
||||
expect(() =>
|
||||
getRoleFromPackage({
|
||||
PackageRoles.getRoleFromPackage({
|
||||
name: 'test',
|
||||
backstage: {},
|
||||
}),
|
||||
).toThrow('Package test must specify a role in the "backstage" field');
|
||||
|
||||
expect(() =>
|
||||
getRoleFromPackage({
|
||||
PackageRoles.getRoleFromPackage({
|
||||
name: 'test',
|
||||
backstage: { role: 'invalid' },
|
||||
}),
|
||||
@@ -77,48 +70,10 @@ describe('getRoleFromPackage', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('findRoleFromCommand', () => {
|
||||
function mkCommand(args: string) {
|
||||
const parsed = new Command()
|
||||
.option('--role <role>', 'test role')
|
||||
.parse(['node', 'entry.js', ...args.split(' ')]) as Command;
|
||||
return parsed.opts();
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
mockFs({
|
||||
'package.json': JSON.stringify({
|
||||
name: 'test',
|
||||
backstage: {
|
||||
role: 'web-library',
|
||||
},
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
mockFs.restore();
|
||||
});
|
||||
|
||||
it('provides role info by role', async () => {
|
||||
await expect(findRoleFromCommand(mkCommand(''))).resolves.toEqual(
|
||||
'web-library',
|
||||
);
|
||||
|
||||
await expect(
|
||||
findRoleFromCommand(mkCommand('--role node-library')),
|
||||
).resolves.toEqual('node-library');
|
||||
|
||||
await expect(
|
||||
findRoleFromCommand(mkCommand('--role invalid')),
|
||||
).rejects.toThrow(`Unknown package role 'invalid'`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('detectRoleFromPackage', () => {
|
||||
it('detects the role of example-app', () => {
|
||||
expect(
|
||||
detectRoleFromPackage({
|
||||
PackageRoles.detectRoleFromPackage({
|
||||
name: 'example-app',
|
||||
private: true,
|
||||
bundled: true,
|
||||
@@ -141,7 +96,7 @@ describe('detectRoleFromPackage', () => {
|
||||
|
||||
it('detects the role of example-backend', () => {
|
||||
expect(
|
||||
detectRoleFromPackage({
|
||||
PackageRoles.detectRoleFromPackage({
|
||||
name: 'example-backend',
|
||||
main: 'dist/index.cjs.js',
|
||||
types: 'src/index.ts',
|
||||
@@ -160,7 +115,7 @@ describe('detectRoleFromPackage', () => {
|
||||
|
||||
it('detects the role of @backstage/plugin-catalog', () => {
|
||||
expect(
|
||||
detectRoleFromPackage({
|
||||
PackageRoles.detectRoleFromPackage({
|
||||
name: '@backstage/plugin-catalog',
|
||||
main: 'src/index.ts',
|
||||
types: 'src/index.ts',
|
||||
@@ -185,7 +140,7 @@ describe('detectRoleFromPackage', () => {
|
||||
|
||||
it('detects the role of @backstage/plugin-catalog-backend', () => {
|
||||
expect(
|
||||
detectRoleFromPackage({
|
||||
PackageRoles.detectRoleFromPackage({
|
||||
name: '@backstage/plugin-catalog-backend',
|
||||
main: 'src/index.ts',
|
||||
types: 'src/index.ts',
|
||||
@@ -209,7 +164,7 @@ describe('detectRoleFromPackage', () => {
|
||||
|
||||
it('detects the role of @backstage/plugin-catalog-react', () => {
|
||||
expect(
|
||||
detectRoleFromPackage({
|
||||
PackageRoles.detectRoleFromPackage({
|
||||
name: '@backstage/plugin-catalog-react',
|
||||
main: 'src/index.ts',
|
||||
types: 'src/index.ts',
|
||||
@@ -232,7 +187,7 @@ describe('detectRoleFromPackage', () => {
|
||||
|
||||
it('detects the role of @backstage/plugin-catalog-common', () => {
|
||||
expect(
|
||||
detectRoleFromPackage({
|
||||
PackageRoles.detectRoleFromPackage({
|
||||
name: '@backstage/plugin-catalog-common',
|
||||
main: 'src/index.ts',
|
||||
types: 'src/index.ts',
|
||||
@@ -256,7 +211,7 @@ describe('detectRoleFromPackage', () => {
|
||||
|
||||
it('detects the role of @backstage/plugin-catalog-backend-module-ldap', () => {
|
||||
expect(
|
||||
detectRoleFromPackage({
|
||||
PackageRoles.detectRoleFromPackage({
|
||||
name: '@backstage/plugin-catalog-backend-module-ldap',
|
||||
main: 'src/index.ts',
|
||||
types: 'src/index.ts',
|
||||
@@ -279,7 +234,7 @@ describe('detectRoleFromPackage', () => {
|
||||
|
||||
it('detects the role of @backstage/plugin-permission-node', () => {
|
||||
expect(
|
||||
detectRoleFromPackage({
|
||||
PackageRoles.detectRoleFromPackage({
|
||||
name: '@backstage/plugin-permission-node',
|
||||
main: 'src/index.ts',
|
||||
types: 'src/index.ts',
|
||||
@@ -303,7 +258,7 @@ describe('detectRoleFromPackage', () => {
|
||||
|
||||
it('detects the role of @backstage/plugin-analytics-module-ga', () => {
|
||||
expect(
|
||||
detectRoleFromPackage({
|
||||
PackageRoles.detectRoleFromPackage({
|
||||
name: '@backstage/plugin-analytics-module-ga',
|
||||
main: 'src/index.ts',
|
||||
types: 'src/index.ts',
|
||||
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Copyright 2022 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 { z } from 'zod';
|
||||
import { PackageRole, PackageRoleInfo } from './types';
|
||||
|
||||
const packageRoleInfos: PackageRoleInfo[] = [
|
||||
{
|
||||
role: 'frontend',
|
||||
platform: 'web',
|
||||
output: ['bundle'],
|
||||
},
|
||||
{
|
||||
role: 'backend',
|
||||
platform: 'node',
|
||||
output: ['bundle'],
|
||||
},
|
||||
{
|
||||
role: 'cli',
|
||||
platform: 'node',
|
||||
output: ['cjs'],
|
||||
},
|
||||
{
|
||||
role: 'web-library',
|
||||
platform: 'web',
|
||||
output: ['types', 'esm'],
|
||||
},
|
||||
{
|
||||
role: 'node-library',
|
||||
platform: 'node',
|
||||
output: ['types', 'cjs'],
|
||||
},
|
||||
{
|
||||
role: 'common-library',
|
||||
platform: 'common',
|
||||
output: ['types', 'esm', 'cjs'],
|
||||
},
|
||||
{
|
||||
role: 'frontend-plugin',
|
||||
platform: 'web',
|
||||
output: ['types', 'esm'],
|
||||
},
|
||||
{
|
||||
role: 'frontend-plugin-module',
|
||||
platform: 'web',
|
||||
output: ['types', 'esm'],
|
||||
},
|
||||
{
|
||||
role: 'backend-plugin',
|
||||
platform: 'node',
|
||||
output: ['types', 'cjs'],
|
||||
},
|
||||
{
|
||||
role: 'backend-plugin-module',
|
||||
platform: 'node',
|
||||
output: ['types', 'cjs'],
|
||||
},
|
||||
];
|
||||
|
||||
const readSchema = z.object({
|
||||
name: z.string().optional(),
|
||||
backstage: z
|
||||
.object({
|
||||
role: z.string().optional(),
|
||||
})
|
||||
.optional(),
|
||||
});
|
||||
|
||||
const detectionSchema = z.object({
|
||||
name: z.string().optional(),
|
||||
scripts: z
|
||||
.object({
|
||||
start: z.string().optional(),
|
||||
build: z.string().optional(),
|
||||
})
|
||||
.optional(),
|
||||
publishConfig: z
|
||||
.object({
|
||||
main: z.string().optional(),
|
||||
types: z.string().optional(),
|
||||
module: z.string().optional(),
|
||||
})
|
||||
.optional(),
|
||||
main: z.string().optional(),
|
||||
types: z.string().optional(),
|
||||
module: z.string().optional(),
|
||||
});
|
||||
|
||||
/**
|
||||
* Utilities for working with Backstage package roles.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export class PackageRoles {
|
||||
/**
|
||||
* Get the associated info for a package role.
|
||||
*/
|
||||
static getRoleInfo(role: string): PackageRoleInfo {
|
||||
const roleInfo = packageRoleInfos.find(r => r.role === role);
|
||||
if (!roleInfo) {
|
||||
throw new Error(`Unknown package role '${role}'`);
|
||||
}
|
||||
return roleInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given package JSON data, get the package role.
|
||||
*/
|
||||
static getRoleFromPackage(pkgJson: unknown): PackageRole | undefined {
|
||||
const pkg = readSchema.parse(pkgJson);
|
||||
|
||||
if (pkg.backstage) {
|
||||
const { role } = pkg.backstage;
|
||||
if (!role) {
|
||||
throw new Error(
|
||||
`Package ${pkg.name} must specify a role in the "backstage" field`,
|
||||
);
|
||||
}
|
||||
|
||||
return this.getRoleInfo(role).role;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to detect the role of a package from its package.json.
|
||||
*/
|
||||
static detectRoleFromPackage(pkgJson: unknown): PackageRole | undefined {
|
||||
const pkg = detectionSchema.parse(pkgJson);
|
||||
|
||||
if (pkg.scripts?.start?.includes('app:serve')) {
|
||||
return 'frontend';
|
||||
}
|
||||
if (pkg.scripts?.build?.includes('backend:bundle')) {
|
||||
return 'backend';
|
||||
}
|
||||
if (
|
||||
pkg.name?.includes('plugin-') &&
|
||||
pkg.name?.includes('-backend-module-')
|
||||
) {
|
||||
return 'backend-plugin-module';
|
||||
}
|
||||
if (pkg.name?.includes('plugin-') && pkg.name?.includes('-module-')) {
|
||||
return 'frontend-plugin-module';
|
||||
}
|
||||
if (pkg.scripts?.start?.includes('plugin:serve')) {
|
||||
return 'frontend-plugin';
|
||||
}
|
||||
if (pkg.scripts?.start?.includes('backend:dev')) {
|
||||
return 'backend-plugin';
|
||||
}
|
||||
|
||||
const mainEntry = pkg.publishConfig?.main || pkg.main;
|
||||
const moduleEntry = pkg.publishConfig?.module || pkg.module;
|
||||
const typesEntry = pkg.publishConfig?.types || pkg.types;
|
||||
if (typesEntry) {
|
||||
if (mainEntry && moduleEntry) {
|
||||
return 'common-library';
|
||||
}
|
||||
if (moduleEntry || mainEntry?.endsWith('.esm.js')) {
|
||||
return 'web-library';
|
||||
}
|
||||
if (mainEntry) {
|
||||
return 'node-library';
|
||||
}
|
||||
} else if (mainEntry) {
|
||||
return 'cli';
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
@@ -20,9 +20,4 @@ export type {
|
||||
PackageOutputType,
|
||||
PackageRole,
|
||||
} from './types';
|
||||
export {
|
||||
getRoleInfo,
|
||||
getRoleFromPackage,
|
||||
findRoleFromCommand,
|
||||
detectRoleFromPackage,
|
||||
} from './PackageRoles';
|
||||
export { PackageRoles } from './PackageRoles';
|
||||
@@ -14,6 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Backstage package role, see {@link https://backstage.io/docs/local-dev/cli-build-system#package-roles | docs}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type PackageRole =
|
||||
| 'frontend'
|
||||
| 'backend'
|
||||
@@ -26,9 +31,25 @@ export type PackageRole =
|
||||
| 'backend-plugin'
|
||||
| 'backend-plugin-module';
|
||||
|
||||
/**
|
||||
* A type of platform that a package can be built for.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type PackagePlatform = 'node' | 'web' | 'common';
|
||||
|
||||
/**
|
||||
* The type of output that a package can produce.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type PackageOutputType = 'bundle' | 'types' | 'esm' | 'cjs';
|
||||
|
||||
/**
|
||||
* Information about a package role.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface PackageRoleInfo {
|
||||
role: PackageRole;
|
||||
platform: PackagePlatform;
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2022 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 mockFs from 'mock-fs';
|
||||
import { Command } from 'commander';
|
||||
import { findRoleFromCommand } from './role';
|
||||
|
||||
describe('findRoleFromCommand', () => {
|
||||
function mkCommand(args: string) {
|
||||
const parsed = new Command()
|
||||
.option('--role <role>', 'test role')
|
||||
.parse(['node', 'entry.js', ...args.split(' ')]) as Command;
|
||||
return parsed.opts();
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
mockFs({
|
||||
'package.json': JSON.stringify({
|
||||
name: 'test',
|
||||
backstage: {
|
||||
role: 'web-library',
|
||||
},
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
mockFs.restore();
|
||||
});
|
||||
|
||||
it('provides role info by role', async () => {
|
||||
await expect(findRoleFromCommand(mkCommand(''))).resolves.toEqual(
|
||||
'web-library',
|
||||
);
|
||||
|
||||
await expect(
|
||||
findRoleFromCommand(mkCommand('--role node-library')),
|
||||
).resolves.toEqual('node-library');
|
||||
|
||||
await expect(
|
||||
findRoleFromCommand(mkCommand('--role invalid')),
|
||||
).rejects.toThrow(`Unknown package role 'invalid'`);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2023 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 { OptionValues } from 'commander';
|
||||
import { paths } from './paths';
|
||||
|
||||
export async function findRoleFromCommand(
|
||||
opts: OptionValues,
|
||||
): Promise<PackageRole> {
|
||||
if (opts.role) {
|
||||
return getRoleInfo(opts.role)?.role;
|
||||
}
|
||||
|
||||
const pkg = await fs.readJson(paths.resolveTarget('package.json'));
|
||||
const info = getRoleFromPackage(pkg);
|
||||
if (!info) {
|
||||
throw new Error(`Target package must have 'backstage.role' set`);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
Reference in New Issue
Block a user