feat: harmonize the package naming with cli
Custom scopes should be named as `backstage-plugin-` while backstage scoped ones shoul be named just `plugin-`. Also allow custom prefix after the scope for example `custom/myapp.` to be used as scope. Signed-off-by: Heikki Hellgren <heikki.hellgren@op.fi>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/cli': patch
|
||||
---
|
||||
|
||||
Harmonize the package naming and allow custom prefix
|
||||
@@ -19,7 +19,7 @@ import chalk from 'chalk';
|
||||
import camelCase from 'lodash/camelCase';
|
||||
import { paths } from '../../paths';
|
||||
import { addCodeownersEntry, getCodeownersFilePath } from '../../codeowners';
|
||||
import { createFactory, CreateContext } from '../types';
|
||||
import { CreateContext, createFactory } from '../types';
|
||||
import { addPackageDependency, Task } from '../../tasks';
|
||||
import {
|
||||
moduleIdIdPrompt,
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
pluginIdPrompt,
|
||||
} from './common/prompts';
|
||||
import { executePluginPackageTemplate } from './common/tasks';
|
||||
import { resolvePackageName } from './common/util';
|
||||
|
||||
type Options = {
|
||||
id: string;
|
||||
@@ -45,9 +46,11 @@ export const backendModule = createFactory<Options>({
|
||||
async create(options: Options, ctx: CreateContext) {
|
||||
const { id: pluginId, moduleId } = options;
|
||||
const dirName = `${pluginId}-backend-module-${moduleId}`;
|
||||
const name = ctx.scope
|
||||
? `@${ctx.scope}/plugin-${dirName}`
|
||||
: `backstage-plugin-${dirName}`;
|
||||
const name = resolvePackageName({
|
||||
baseName: dirName,
|
||||
scope: ctx.scope,
|
||||
plugin: true,
|
||||
});
|
||||
|
||||
Task.log();
|
||||
Task.log(`Creating backend module ${chalk.cyan(name)}`);
|
||||
|
||||
@@ -19,10 +19,11 @@ import chalk from 'chalk';
|
||||
import camelCase from 'lodash/camelCase';
|
||||
import { paths } from '../../paths';
|
||||
import { addCodeownersEntry, getCodeownersFilePath } from '../../codeowners';
|
||||
import { createFactory, CreateContext } from '../types';
|
||||
import { CreateContext, createFactory } from '../types';
|
||||
import { addPackageDependency, Task } from '../../tasks';
|
||||
import { ownerPrompt, pluginIdPrompt } from './common/prompts';
|
||||
import { executePluginPackageTemplate } from './common/tasks';
|
||||
import { resolvePackageName } from './common/util';
|
||||
|
||||
type Options = {
|
||||
id: string;
|
||||
@@ -40,9 +41,11 @@ export const backendPlugin = createFactory<Options>({
|
||||
async create(options: Options, ctx: CreateContext) {
|
||||
const { id } = options;
|
||||
const pluginId = `${id}-backend`;
|
||||
const name = ctx.scope
|
||||
? `@${ctx.scope}/plugin-${pluginId}`
|
||||
: `backstage-plugin-${pluginId}`;
|
||||
const name = resolvePackageName({
|
||||
baseName: pluginId,
|
||||
scope: ctx.scope,
|
||||
plugin: true,
|
||||
});
|
||||
|
||||
Task.log();
|
||||
Task.log(`Creating backend plugin ${chalk.cyan(name)}`);
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2024 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 { resolvePackageName } from './util';
|
||||
|
||||
describe('resolvePackageName', () => {
|
||||
it('should generate correct name without scope', () => {
|
||||
expect(resolvePackageName({ baseName: 'test', plugin: true })).toEqual(
|
||||
'backstage-plugin-test',
|
||||
);
|
||||
expect(resolvePackageName({ baseName: 'test', plugin: false })).toEqual(
|
||||
'test',
|
||||
);
|
||||
});
|
||||
|
||||
it('should generate correct name for backstage scope', () => {
|
||||
expect(
|
||||
resolvePackageName({
|
||||
baseName: 'test',
|
||||
scope: 'backstage',
|
||||
plugin: true,
|
||||
}),
|
||||
).toEqual('@backstage/plugin-test');
|
||||
expect(
|
||||
resolvePackageName({
|
||||
baseName: 'test',
|
||||
scope: 'backstage',
|
||||
plugin: false,
|
||||
}),
|
||||
).toEqual('@backstage/test');
|
||||
});
|
||||
|
||||
it('should generate correct name for custom scope', () => {
|
||||
expect(
|
||||
resolvePackageName({
|
||||
baseName: 'test',
|
||||
scope: 'custom',
|
||||
plugin: true,
|
||||
}),
|
||||
).toEqual('@custom/backstage-plugin-test');
|
||||
expect(
|
||||
resolvePackageName({
|
||||
baseName: 'test',
|
||||
scope: 'custom',
|
||||
plugin: false,
|
||||
}),
|
||||
).toEqual('@custom/test');
|
||||
});
|
||||
|
||||
it('should generate correct name for custom scope and custom prefix', () => {
|
||||
expect(
|
||||
resolvePackageName({
|
||||
baseName: 'test',
|
||||
scope: 'custom/myapp.',
|
||||
plugin: true,
|
||||
}),
|
||||
).toEqual('@custom/myapp.backstage-plugin-test');
|
||||
expect(
|
||||
resolvePackageName({
|
||||
baseName: 'test',
|
||||
scope: 'custom/myapp.',
|
||||
plugin: false,
|
||||
}),
|
||||
).toEqual('@custom/myapp.test');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2024 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.
|
||||
*/
|
||||
|
||||
export const resolvePackageName = (options: {
|
||||
baseName: string;
|
||||
scope?: string;
|
||||
plugin: boolean;
|
||||
}) => {
|
||||
const { baseName, scope, plugin } = options;
|
||||
if (scope) {
|
||||
if (plugin) {
|
||||
const pluginName = scope.startsWith('backstage')
|
||||
? 'plugin'
|
||||
: 'backstage-plugin';
|
||||
return scope.includes('/')
|
||||
? `@${scope}${pluginName}-${baseName}`
|
||||
: `@${scope}/${pluginName}-${baseName}`;
|
||||
}
|
||||
return scope.includes('/')
|
||||
? `@${scope}${baseName}`
|
||||
: `@${scope}/${baseName}`;
|
||||
}
|
||||
|
||||
return plugin ? `backstage-plugin-${baseName}` : baseName;
|
||||
};
|
||||
@@ -180,7 +180,7 @@ const router = (
|
||||
fs.readJson(mockDir.resolve('packages/app/package.json')),
|
||||
).resolves.toEqual({
|
||||
dependencies: {
|
||||
'@internal/plugin-test': '^1.0.0',
|
||||
'@internal/backstage-plugin-test': '^1.0.0',
|
||||
},
|
||||
});
|
||||
|
||||
@@ -188,7 +188,7 @@ const router = (
|
||||
fs.readFile(mockDir.resolve('packages/app/src/App.tsx'), 'utf8'),
|
||||
).resolves.toBe(`
|
||||
import { createApp } from '@backstage/app-defaults';
|
||||
import { TestPage } from '@internal/plugin-test';
|
||||
import { TestPage } from '@internal/backstage-plugin-test';
|
||||
|
||||
const router = (
|
||||
<FlatRoutes>
|
||||
|
||||
@@ -20,10 +20,11 @@ import camelCase from 'lodash/camelCase';
|
||||
import upperFirst from 'lodash/upperFirst';
|
||||
import { paths } from '../../paths';
|
||||
import { addCodeownersEntry, getCodeownersFilePath } from '../../codeowners';
|
||||
import { createFactory, CreateContext } from '../types';
|
||||
import { CreateContext, createFactory } from '../types';
|
||||
import { addPackageDependency, Task } from '../../tasks';
|
||||
import { ownerPrompt, pluginIdPrompt } from './common/prompts';
|
||||
import { executePluginPackageTemplate } from './common/tasks';
|
||||
import { resolvePackageName } from './common/util';
|
||||
|
||||
type Options = {
|
||||
id: string;
|
||||
@@ -41,9 +42,11 @@ export const frontendPlugin = createFactory<Options>({
|
||||
async create(options: Options, ctx: CreateContext) {
|
||||
const { id } = options;
|
||||
|
||||
const name = ctx.scope
|
||||
? `@${ctx.scope}/plugin-${id}`
|
||||
: `backstage-plugin-${id}`;
|
||||
const name = resolvePackageName({
|
||||
baseName: id,
|
||||
scope: ctx.scope,
|
||||
plugin: true,
|
||||
});
|
||||
const extensionName = `${upperFirst(camelCase(id))}Page`;
|
||||
|
||||
Task.log();
|
||||
|
||||
@@ -17,10 +17,11 @@
|
||||
import chalk from 'chalk';
|
||||
import { paths } from '../../paths';
|
||||
import { addCodeownersEntry, getCodeownersFilePath } from '../../codeowners';
|
||||
import { createFactory, CreateContext } from '../types';
|
||||
import { CreateContext, createFactory } from '../types';
|
||||
import { Task } from '../../tasks';
|
||||
import { ownerPrompt, pluginIdPrompt } from './common/prompts';
|
||||
import { executePluginPackageTemplate } from './common/tasks';
|
||||
import { resolvePackageName } from './common/util';
|
||||
|
||||
type Options = {
|
||||
id: string;
|
||||
@@ -37,7 +38,11 @@ export const nodeLibraryPackage = createFactory<Options>({
|
||||
optionsPrompts: [pluginIdPrompt(), ownerPrompt()],
|
||||
async create(options: Options, ctx: CreateContext) {
|
||||
const { id } = options;
|
||||
const name = ctx.scope ? `@${ctx.scope}/${id}` : `${id}`;
|
||||
const name = resolvePackageName({
|
||||
baseName: id,
|
||||
scope: ctx.scope,
|
||||
plugin: false,
|
||||
});
|
||||
|
||||
Task.log();
|
||||
Task.log(`Creating node-library package ${chalk.cyan(name)}`);
|
||||
|
||||
@@ -17,10 +17,11 @@
|
||||
import chalk from 'chalk';
|
||||
import { paths } from '../../paths';
|
||||
import { addCodeownersEntry, getCodeownersFilePath } from '../../codeowners';
|
||||
import { createFactory, CreateContext } from '../types';
|
||||
import { CreateContext, createFactory } from '../types';
|
||||
import { Task } from '../../tasks';
|
||||
import { ownerPrompt, pluginIdPrompt } from './common/prompts';
|
||||
import { executePluginPackageTemplate } from './common/tasks';
|
||||
import { resolvePackageName } from './common/util';
|
||||
|
||||
type Options = {
|
||||
id: string;
|
||||
@@ -38,9 +39,11 @@ export const pluginCommon = createFactory<Options>({
|
||||
async create(options: Options, ctx: CreateContext) {
|
||||
const { id } = options;
|
||||
const suffix = `${id}-common`;
|
||||
const name = ctx.scope
|
||||
? `@${ctx.scope}/plugin-${suffix}`
|
||||
: `backstage-plugin-${suffix}`;
|
||||
const name = resolvePackageName({
|
||||
baseName: suffix,
|
||||
scope: ctx.scope,
|
||||
plugin: true,
|
||||
});
|
||||
|
||||
Task.log();
|
||||
Task.log(`Creating backend plugin ${chalk.cyan(name)}`);
|
||||
|
||||
@@ -17,10 +17,11 @@
|
||||
import chalk from 'chalk';
|
||||
import { paths } from '../../paths';
|
||||
import { addCodeownersEntry, getCodeownersFilePath } from '../../codeowners';
|
||||
import { createFactory, CreateContext } from '../types';
|
||||
import { CreateContext, createFactory } from '../types';
|
||||
import { Task } from '../../tasks';
|
||||
import { ownerPrompt, pluginIdPrompt } from './common/prompts';
|
||||
import { executePluginPackageTemplate } from './common/tasks';
|
||||
import { resolvePackageName } from './common/util';
|
||||
|
||||
type Options = {
|
||||
id: string;
|
||||
@@ -38,9 +39,11 @@ export const pluginNode = createFactory<Options>({
|
||||
async create(options: Options, ctx: CreateContext) {
|
||||
const { id } = options;
|
||||
const suffix = `${id}-node`;
|
||||
const name = ctx.scope
|
||||
? `@${ctx.scope}/plugin-${suffix}`
|
||||
: `backstage-plugin-${suffix}`;
|
||||
const name = resolvePackageName({
|
||||
baseName: suffix,
|
||||
scope: ctx.scope,
|
||||
plugin: true,
|
||||
});
|
||||
|
||||
Task.log();
|
||||
Task.log(`Creating Node.js plugin library ${chalk.cyan(name)}`);
|
||||
|
||||
@@ -17,10 +17,11 @@
|
||||
import chalk from 'chalk';
|
||||
import { paths } from '../../paths';
|
||||
import { addCodeownersEntry, getCodeownersFilePath } from '../../codeowners';
|
||||
import { createFactory, CreateContext } from '../types';
|
||||
import { CreateContext, createFactory } from '../types';
|
||||
import { Task } from '../../tasks';
|
||||
import { ownerPrompt, pluginIdPrompt } from './common/prompts';
|
||||
import { executePluginPackageTemplate } from './common/tasks';
|
||||
import { resolvePackageName } from './common/util';
|
||||
|
||||
type Options = {
|
||||
id: string;
|
||||
@@ -38,9 +39,11 @@ export const pluginWeb = createFactory<Options>({
|
||||
async create(options: Options, ctx: CreateContext) {
|
||||
const { id } = options;
|
||||
const suffix = `${id}-react`;
|
||||
const name = ctx.scope
|
||||
? `@${ctx.scope}/plugin-${suffix}`
|
||||
: `backstage-plugin-${suffix}`;
|
||||
const name = resolvePackageName({
|
||||
baseName: suffix,
|
||||
scope: ctx.scope,
|
||||
plugin: true,
|
||||
});
|
||||
|
||||
Task.log();
|
||||
Task.log(`Creating web plugin library ${chalk.cyan(name)}`);
|
||||
|
||||
@@ -17,10 +17,11 @@
|
||||
import chalk from 'chalk';
|
||||
import { paths } from '../../paths';
|
||||
import { addCodeownersEntry, getCodeownersFilePath } from '../../codeowners';
|
||||
import { createFactory, CreateContext } from '../types';
|
||||
import { CreateContext, createFactory } from '../types';
|
||||
import { Task } from '../../tasks';
|
||||
import { ownerPrompt } from './common/prompts';
|
||||
import { executePluginPackageTemplate } from './common/tasks';
|
||||
import { resolvePackageName } from './common/util';
|
||||
|
||||
type Options = {
|
||||
id: string;
|
||||
@@ -55,14 +56,11 @@ export const scaffolderModule = createFactory<Options>({
|
||||
const { id } = options;
|
||||
const slug = `scaffolder-backend-module-${id}`;
|
||||
|
||||
let name = `backstage-plugin-${slug}`;
|
||||
if (ctx.scope) {
|
||||
if (ctx.scope === 'backstage') {
|
||||
name = `@backstage/plugin-${slug}`;
|
||||
} else {
|
||||
name = `@${ctx.scope}/backstage-plugin-${slug}`;
|
||||
}
|
||||
}
|
||||
const name = resolvePackageName({
|
||||
baseName: slug,
|
||||
scope: ctx.scope,
|
||||
plugin: true,
|
||||
});
|
||||
|
||||
Task.log();
|
||||
Task.log(`Creating module ${chalk.cyan(name)}`);
|
||||
|
||||
@@ -17,10 +17,11 @@
|
||||
import chalk from 'chalk';
|
||||
import { paths } from '../../paths';
|
||||
import { addCodeownersEntry, getCodeownersFilePath } from '../../codeowners';
|
||||
import { createFactory, CreateContext } from '../types';
|
||||
import { CreateContext, createFactory } from '../types';
|
||||
import { Task } from '../../tasks';
|
||||
import { ownerPrompt, pluginIdPrompt } from './common/prompts';
|
||||
import { executePluginPackageTemplate } from './common/tasks';
|
||||
import { resolvePackageName } from './common/util';
|
||||
|
||||
type Options = {
|
||||
id: string;
|
||||
@@ -37,7 +38,11 @@ export const webLibraryPackage = createFactory<Options>({
|
||||
optionsPrompts: [pluginIdPrompt(), ownerPrompt()],
|
||||
async create(options: Options, ctx: CreateContext) {
|
||||
const { id } = options;
|
||||
const name = ctx.scope ? `@${ctx.scope}/${id}` : `${id}`;
|
||||
const name = resolvePackageName({
|
||||
baseName: id,
|
||||
scope: ctx.scope,
|
||||
plugin: false,
|
||||
});
|
||||
|
||||
Task.log();
|
||||
Task.log(`Creating web-library package ${chalk.cyan(name)}`);
|
||||
|
||||
Reference in New Issue
Block a user