merge with master and resolve yarn.lock conflict
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -1,5 +1,137 @@
|
||||
# @backstage/cli
|
||||
|
||||
## 0.26.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- eeb226a: Updated dependency `rollup` to `^4.0.0`.
|
||||
- 91192f4: Updated backend plugin template to work better with new backend system
|
||||
- cc371d6: Ignore transforming only on `react-use/lib`, not whole `react-use` in jest.
|
||||
|
||||
** POTENTIAL BREAKAGE **
|
||||
If your tests fail, please change to use path import from `react-use/esm/`. It is also recommended to migrate from `react-user/lib` imports to `react-use/esm`
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/catalog-model@1.4.5
|
||||
- @backstage/cli-common@0.1.13
|
||||
- @backstage/cli-node@0.2.4
|
||||
- @backstage/config@1.2.0
|
||||
- @backstage/config-loader@1.7.0
|
||||
- @backstage/errors@1.2.4
|
||||
- @backstage/eslint-plugin@0.1.6
|
||||
- @backstage/integration@1.9.1
|
||||
- @backstage/release-manifests@0.0.11
|
||||
- @backstage/types@1.1.1
|
||||
|
||||
## 0.26.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- eeb226a: Updated dependency `rollup` to `^4.0.0`.
|
||||
- cc371d6: Ignore transforming only on `react-use/lib`, not whole `react-use` in jest.
|
||||
|
||||
** POTENTIAL BREAKAGE **
|
||||
If your tests fail, please change to use path import from `react-use/esm/`. It is also recommended to migrate from `react-user/lib` imports to `react-use/esm`
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/catalog-model@1.4.5
|
||||
- @backstage/cli-common@0.1.13
|
||||
- @backstage/cli-node@0.2.4
|
||||
- @backstage/config@1.2.0
|
||||
- @backstage/config-loader@1.7.0
|
||||
- @backstage/errors@1.2.4
|
||||
- @backstage/eslint-plugin@0.1.6
|
||||
- @backstage/integration@1.9.1
|
||||
- @backstage/release-manifests@0.0.11
|
||||
- @backstage/types@1.1.1
|
||||
|
||||
## 0.26.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 0d72065: The backend devlopment server transpilation has been replaced with a simplified solution based on SWC, which is already the transpiler used for tests. This fixed an issue where never versions of the `tsx` dependency had a new contract for signalling dependencies, breaking watch mode. This change fixed file watches as well as enables sourcemaps.
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- fe1a55e: Extend option to minify generated code to the `backend` package.
|
||||
- b0875e5: Fixed a bug that could cause the `build-workspace` command to fail when invoked with `--alwaysYarnPack` enabled in environments with limited resources.
|
||||
- bdf9ec1: New backend plugins with cli are now created using the new backend system
|
||||
- cadbb82: Added a `EXPERIMENTAL_LAZY_COMPILATION` flag, which enables the experimental Webpack lazy compilation option in frontend builds.
|
||||
- 999224f: Bump dependency `minimatch` to v9
|
||||
- 1bd4596: Removed the `ts-node` dev dependency.
|
||||
- 8dce287: Fix prettier issues on default plugins & module templates
|
||||
- f86e34c: Removed unused `replace-in-file` dependency
|
||||
- 2398c7c: Updated dependency `@spotify/prettier-config` to `^15.0.0`.
|
||||
Updated dependency `@spotify/eslint-config-base` to `^15.0.0`.
|
||||
Updated dependency `@spotify/eslint-config-react` to `^15.0.0`.
|
||||
Updated dependency `@spotify/eslint-config-typescript` to `^15.0.0`.
|
||||
- f4404e5: Add .ico import support
|
||||
- f39dfd3: Tweak the descriptions of the CLI templates
|
||||
- Updated dependencies
|
||||
- @backstage/integration@1.9.1
|
||||
- @backstage/config@1.2.0
|
||||
- @backstage/errors@1.2.4
|
||||
- @backstage/eslint-plugin@0.1.6
|
||||
- @backstage/config-loader@1.7.0
|
||||
- @backstage/cli-node@0.2.4
|
||||
- @backstage/catalog-model@1.4.5
|
||||
- @backstage/cli-common@0.1.13
|
||||
- @backstage/release-manifests@0.0.11
|
||||
- @backstage/types@1.1.1
|
||||
|
||||
## 0.25.3-next.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- f39dfd3: Tweak the descriptions of the CLI templates
|
||||
- Updated dependencies
|
||||
- @backstage/integration@1.9.1-next.2
|
||||
- @backstage/catalog-model@1.4.5-next.0
|
||||
- @backstage/cli-common@0.1.13
|
||||
- @backstage/cli-node@0.2.4-next.0
|
||||
- @backstage/config@1.2.0-next.1
|
||||
- @backstage/config-loader@1.7.0-next.1
|
||||
- @backstage/errors@1.2.4-next.0
|
||||
- @backstage/eslint-plugin@0.1.6-next.0
|
||||
- @backstage/release-manifests@0.0.11
|
||||
- @backstage/types@1.1.1
|
||||
|
||||
## 0.25.3-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 8dce287: Fix prettier issues on default plugins & module templates
|
||||
- Updated dependencies
|
||||
- @backstage/config@1.2.0-next.1
|
||||
- @backstage/config-loader@1.7.0-next.1
|
||||
- @backstage/integration@1.9.1-next.1
|
||||
- @backstage/catalog-model@1.4.5-next.0
|
||||
- @backstage/cli-common@0.1.13
|
||||
- @backstage/cli-node@0.2.4-next.0
|
||||
- @backstage/errors@1.2.4-next.0
|
||||
- @backstage/eslint-plugin@0.1.6-next.0
|
||||
- @backstage/release-manifests@0.0.11
|
||||
- @backstage/types@1.1.1
|
||||
|
||||
## 0.25.3-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 999224f: Bump dependency `minimatch` to v9
|
||||
- f86e34c: Removed unused `replace-in-file` dependency
|
||||
- f4404e5: Add .ico import support
|
||||
- Updated dependencies
|
||||
- @backstage/errors@1.2.4-next.0
|
||||
- @backstage/eslint-plugin@0.1.6-next.0
|
||||
- @backstage/cli-node@0.2.4-next.0
|
||||
- @backstage/config-loader@1.6.3-next.0
|
||||
- @backstage/catalog-model@1.4.5-next.0
|
||||
- @backstage/config@1.1.2-next.0
|
||||
- @backstage/integration@1.9.1-next.0
|
||||
- @backstage/cli-common@0.1.13
|
||||
- @backstage/release-manifests@0.0.11
|
||||
- @backstage/types@1.1.1
|
||||
|
||||
## 0.25.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -24,14 +24,6 @@ const isLocal = require('fs').existsSync(path.resolve(__dirname, '../src'));
|
||||
if (!isLocal || process.env.BACKSTAGE_E2E_CLI_TEST) {
|
||||
require('..');
|
||||
} else {
|
||||
require('ts-node').register({
|
||||
transpileOnly: true,
|
||||
/* eslint-disable-next-line no-restricted-syntax */
|
||||
project: path.resolve(__dirname, '../../../tsconfig.json'),
|
||||
compilerOptions: {
|
||||
module: 'CommonJS',
|
||||
},
|
||||
});
|
||||
|
||||
require('@backstage/cli/config/nodeTransform.cjs');
|
||||
require('../src');
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ const transformIgnorePattern = [
|
||||
'highlight\\.js',
|
||||
'prismjs',
|
||||
'json-schema',
|
||||
'react-use',
|
||||
'react-use/lib',
|
||||
'typescript',
|
||||
].join('|');
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
const { transformSync } = require('@swc/core');
|
||||
const { addHook } = require('pirates');
|
||||
|
||||
addHook(
|
||||
(code, filename) => {
|
||||
const transformed = transformSync(code, {
|
||||
filename,
|
||||
sourceMaps: 'inline',
|
||||
module: { type: 'commonjs' },
|
||||
jsc: {
|
||||
target: 'es2022',
|
||||
parser: {
|
||||
syntax: 'typescript',
|
||||
},
|
||||
},
|
||||
});
|
||||
process.send?.({ type: 'watch', path: filename });
|
||||
return transformed.code;
|
||||
},
|
||||
{ extensions: ['.ts', '.cts'], ignoreNodeModules: true },
|
||||
);
|
||||
|
||||
addHook(
|
||||
(code, filename) => {
|
||||
process.send?.({ type: 'watch', path: filename });
|
||||
return code;
|
||||
},
|
||||
{ extensions: ['.js', '.cjs'], ignoreNodeModules: true },
|
||||
);
|
||||
@@ -25,6 +25,7 @@
|
||||
| @swc/core | package.json | error |
|
||||
| @swc/jest | package.json | error |
|
||||
| esbuild | package.json | error |
|
||||
| pirates | package.json | error |
|
||||
| postcss | package.json | error |
|
||||
| process | package.json | error |
|
||||
| sucrase | package.json | error |
|
||||
@@ -32,7 +33,7 @@
|
||||
| glob | package.json | error |
|
||||
| util | package.json | error |
|
||||
|
||||
## Unused devDependencies (12)
|
||||
## Unused devDependencies (11)
|
||||
|
||||
| Name | Location | Severity |
|
||||
| :-------------------------------------- | :----------- | :------- |
|
||||
@@ -46,7 +47,6 @@
|
||||
| @types/svgo | package.json | error |
|
||||
| @types/ejs | package.json | error |
|
||||
| nodemon | package.json | error |
|
||||
| ts-node | package.json | error |
|
||||
| del | package.json | error |
|
||||
|
||||
## Referenced optional peerDependencies (4)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@backstage/cli",
|
||||
"description": "CLI for developing Backstage plugins and apps",
|
||||
"version": "0.25.2",
|
||||
"version": "0.26.2",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
@@ -50,9 +50,9 @@
|
||||
"@rollup/plugin-json": "^6.0.0",
|
||||
"@rollup/plugin-node-resolve": "^15.0.0",
|
||||
"@rollup/plugin-yaml": "^4.0.0",
|
||||
"@spotify/eslint-config-base": "^14.0.0",
|
||||
"@spotify/eslint-config-react": "^14.0.0",
|
||||
"@spotify/eslint-config-typescript": "^14.0.0",
|
||||
"@spotify/eslint-config-base": "^15.0.0",
|
||||
"@spotify/eslint-config-react": "^15.0.0",
|
||||
"@spotify/eslint-config-typescript": "^15.0.0",
|
||||
"@sucrase/webpack-loader": "^2.0.0",
|
||||
"@svgr/core": "6.5.x",
|
||||
"@svgr/plugin-jsx": "6.5.x",
|
||||
@@ -112,15 +112,17 @@
|
||||
"node-libs-browser": "^2.2.1",
|
||||
"npm-packlist": "^5.0.0",
|
||||
"ora": "^5.3.0",
|
||||
"p-limit": "^3.1.0",
|
||||
"p-queue": "^6.6.2",
|
||||
"pirates": "^4.0.6",
|
||||
"postcss": "^8.1.0",
|
||||
"process": "^0.11.10",
|
||||
"react-dev-utils": "^12.0.0-next.60",
|
||||
"react-refresh": "^0.14.0",
|
||||
"recursive-readdir": "^2.2.2",
|
||||
"rollup": "^2.60.2",
|
||||
"rollup-plugin-dts": "^4.0.1",
|
||||
"rollup-plugin-esbuild": "^4.7.2",
|
||||
"rollup": "^4.0.0",
|
||||
"rollup-plugin-dts": "^6.1.0",
|
||||
"rollup-plugin-esbuild": "^6.1.1",
|
||||
"rollup-plugin-postcss": "^4.0.0",
|
||||
"rollup-pluginutils": "^2.8.2",
|
||||
"run-script-webpack-plugin": "^0.2.0",
|
||||
@@ -130,7 +132,6 @@
|
||||
"swc-loader": "^0.2.3",
|
||||
"tar": "^6.1.12",
|
||||
"terser-webpack-plugin": "^5.1.3",
|
||||
"tsx": "^4.0.0",
|
||||
"util": "^0.12.3",
|
||||
"webpack": "^5.70.0",
|
||||
"webpack-dev-server": "^5.0.0",
|
||||
@@ -167,10 +168,13 @@
|
||||
"@types/tar": "^6.1.1",
|
||||
"@types/terser-webpack-plugin": "^5.0.4",
|
||||
"@types/yarnpkg__lockfile": "^1.1.4",
|
||||
"@vitejs/plugin-react": "^4.0.4",
|
||||
"del": "^7.0.0",
|
||||
"msw": "^1.0.0",
|
||||
"nodemon": "^3.0.1",
|
||||
"ts-node": "^10.0.0"
|
||||
"vite": "^4.4.9",
|
||||
"vite-plugin-html": "^3.2.0",
|
||||
"vite-plugin-node-polyfills": "^0.21.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@vitejs/plugin-react": "^4.0.4",
|
||||
|
||||
@@ -29,17 +29,19 @@ interface BuildBackendOptions {
|
||||
targetDir: string;
|
||||
skipBuildDependencies: boolean;
|
||||
configPaths?: string[];
|
||||
minify?: boolean;
|
||||
}
|
||||
|
||||
export async function buildBackend(options: BuildBackendOptions) {
|
||||
const { targetDir, skipBuildDependencies, configPaths } = options;
|
||||
const { targetDir, skipBuildDependencies, configPaths, minify } = options;
|
||||
const pkg = await fs.readJson(resolvePath(targetDir, 'package.json'));
|
||||
|
||||
// We build the target package without generating type declarations.
|
||||
await buildPackage({
|
||||
targetDir: options.targetDir,
|
||||
targetDir,
|
||||
packageJson: pkg,
|
||||
outputs: new Set([Output.cjs]),
|
||||
minify,
|
||||
});
|
||||
|
||||
const tmpDir = await fs.mkdtemp(resolvePath(os.tmpdir(), 'backstage-bundle'));
|
||||
@@ -51,6 +53,7 @@ export async function buildBackend(options: BuildBackendOptions) {
|
||||
buildExcludes: [pkg.name],
|
||||
parallelism: getEnvironmentParallelism(),
|
||||
skeleton: SKELETON_FILE,
|
||||
minify,
|
||||
});
|
||||
|
||||
// We built the target backend package using the regular build process, but the result of
|
||||
|
||||
@@ -45,6 +45,7 @@ export async function command(opts: OptionValues): Promise<void> {
|
||||
targetDir: paths.targetDir,
|
||||
configPaths,
|
||||
skipBuildDependencies: Boolean(opts.skipBuildDependencies),
|
||||
minify: Boolean(opts.minify),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ export function registerScriptCommand(program: Command) {
|
||||
.option('--role <name>', 'Run the command with an explicit package role')
|
||||
.option(
|
||||
'--minify',
|
||||
'Minify the generated code. Does not apply to app or backend packages.',
|
||||
'Minify the generated code. Does not apply to app package (app is minified by default).',
|
||||
)
|
||||
.option(
|
||||
'--skip-build-dependencies',
|
||||
|
||||
@@ -179,6 +179,7 @@ export async function command(opts: OptionValues, cmd: Command): Promise<void> {
|
||||
await buildBackend({
|
||||
targetDir: pkg.dir,
|
||||
skipBuildDependencies: true,
|
||||
minify: buildOptions.minify,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@@ -25,7 +25,11 @@ import svgr from '@svgr/rollup';
|
||||
import dts from 'rollup-plugin-dts';
|
||||
import json from '@rollup/plugin-json';
|
||||
import yaml from '@rollup/plugin-yaml';
|
||||
import { RollupOptions, OutputOptions, RollupWarning } from 'rollup';
|
||||
import {
|
||||
RollupOptions,
|
||||
OutputOptions,
|
||||
WarningHandlerWithDefault,
|
||||
} from 'rollup';
|
||||
|
||||
import { forwardFileImports } from './plugins';
|
||||
import { BuildOptions, Output } from './types';
|
||||
@@ -61,7 +65,7 @@ export async function makeRollupConfigs(
|
||||
targetPkg = (await fs.readJson(packagePath)) as BackstagePackageJson;
|
||||
}
|
||||
|
||||
const onwarn = ({ code, message }: RollupWarning) => {
|
||||
const onwarn: WarningHandlerWithDefault = ({ code, message }) => {
|
||||
if (code === 'EMPTY_BUNDLE') {
|
||||
return; // We don't care about this one
|
||||
}
|
||||
@@ -89,6 +93,7 @@ export async function makeRollupConfigs(
|
||||
entryFileNames: `[name].cjs.js`,
|
||||
chunkFileNames: `cjs/[name]-[hash].cjs.js`,
|
||||
format: 'commonjs',
|
||||
interop: 'compat',
|
||||
sourcemap: true,
|
||||
exports: 'named',
|
||||
});
|
||||
|
||||
@@ -224,6 +224,9 @@ export async function createConfig(
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
experiments: {
|
||||
lazyCompilation: yn(process.env.EXPERIMENTAL_LAZY_COMPILATION),
|
||||
},
|
||||
plugins,
|
||||
...(withCache
|
||||
? {
|
||||
|
||||
@@ -22,22 +22,16 @@ import { ctrlc } from 'ctrlc-windows';
|
||||
import { IpcServer } from './IpcServer';
|
||||
import { ServerDataStore } from './ServerDataStore';
|
||||
import debounce from 'lodash/debounce';
|
||||
import { fileURLToPath, pathToFileURL } from 'url';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { isAbsolute as isAbsolutePath } from 'path';
|
||||
import { paths } from '../paths';
|
||||
import spawn from 'cross-spawn';
|
||||
|
||||
const [nodeMajor, nodeMinor] = process.versions.node.split('.').map(Number);
|
||||
const supportsModuleLoaderRegister =
|
||||
nodeMajor > 20 ||
|
||||
(nodeMajor === 20 && nodeMinor >= 6) ||
|
||||
(nodeMajor === 18 && nodeMinor >= 19);
|
||||
|
||||
const loaderArgs = [
|
||||
'--enable-source-maps',
|
||||
'--require',
|
||||
require.resolve('tsx/preflight'),
|
||||
supportsModuleLoaderRegister ? '--import' : '--loader',
|
||||
pathToFileURL(require.resolve('tsx')).toString(), // Windows prefers a URL here
|
||||
require.resolve('@backstage/cli/config/nodeTransform.cjs'),
|
||||
// TODO: Support modules, although there's currently no way to load them since import() is transpiled tp require()
|
||||
];
|
||||
|
||||
export async function startBackendExperimental(options: BackendServeOptions) {
|
||||
@@ -51,11 +45,21 @@ export async function startBackendExperimental(options: BackendServeOptions) {
|
||||
ServerDataStore.bind(server);
|
||||
|
||||
let exiting = false;
|
||||
let firstStart = true;
|
||||
let child: ChildProcess | undefined;
|
||||
let watcher: FSWatcher | undefined = undefined;
|
||||
let shutdownPromise: Promise<void> | undefined = undefined;
|
||||
|
||||
const watchedPaths = new Set<string>();
|
||||
|
||||
const restart = debounce(async () => {
|
||||
if (firstStart) {
|
||||
firstStart = false;
|
||||
} else {
|
||||
console.log();
|
||||
console.log('Change detected, restarting the development server...');
|
||||
console.log();
|
||||
}
|
||||
// If a re-trigger happens during an existing shutdown, we just ignore it
|
||||
if (shutdownPromise) {
|
||||
return;
|
||||
@@ -115,14 +119,18 @@ export async function startBackendExperimental(options: BackendServeOptions) {
|
||||
|
||||
// This captures messages sent by @esbuild-kit/cjs-loader
|
||||
child.on('message', (data: { type?: string } | null) => {
|
||||
if (typeof data === 'object' && data?.type === 'dependency') {
|
||||
if (!watcher) {
|
||||
return;
|
||||
}
|
||||
if (typeof data === 'object' && data?.type === 'watch') {
|
||||
let path = (data as { path: string }).path;
|
||||
if (path.startsWith('file:')) {
|
||||
path = fileURLToPath(path);
|
||||
}
|
||||
|
||||
if (isAbsolutePath(path)) {
|
||||
watcher?.add(path);
|
||||
if (isAbsolutePath(path) && !watchedPaths.has(path)) {
|
||||
watchedPaths.add(path);
|
||||
watcher.add(path);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -130,7 +138,7 @@ export async function startBackendExperimental(options: BackendServeOptions) {
|
||||
|
||||
restart();
|
||||
|
||||
watcher = watch([], {
|
||||
watcher = watch(['./package.json'], {
|
||||
cwd: process.cwd(),
|
||||
ignoreInitial: true,
|
||||
ignorePermissionErrors: true,
|
||||
|
||||
@@ -38,7 +38,8 @@ type Options = {
|
||||
|
||||
export const backendModule = createFactory<Options>({
|
||||
name: 'backend-module',
|
||||
description: 'A new backend module',
|
||||
description:
|
||||
'A new backend module that extends an existing backend plugin with additional features',
|
||||
optionsDiscovery: async () => ({
|
||||
codeOwnersPath: await getCodeownersFilePath(paths.targetRoot),
|
||||
}),
|
||||
|
||||
@@ -79,13 +79,13 @@ describe('backendPlugin factory', () => {
|
||||
'Executing Template:',
|
||||
'copying .eslintrc.js',
|
||||
'templating README.md.hbs',
|
||||
'templating index.ts.hbs',
|
||||
'templating package.json.hbs',
|
||||
'copying index.ts',
|
||||
'templating run.ts.hbs',
|
||||
'copying setupTests.ts',
|
||||
'copying router.test.ts',
|
||||
'copying router.ts',
|
||||
'templating standaloneServer.ts.hbs',
|
||||
'templating plugin.ts.hbs',
|
||||
'Installing:',
|
||||
`moving plugins${sep}test-backend`,
|
||||
'backend adding dependency',
|
||||
@@ -98,15 +98,6 @@ describe('backendPlugin factory', () => {
|
||||
'backstage-plugin-test-backend': '^1.0.0',
|
||||
},
|
||||
});
|
||||
const standaloneServerFile = await fs.readFile(
|
||||
mockDir.resolve('plugins/test-backend/src/service/standaloneServer.ts'),
|
||||
'utf-8',
|
||||
);
|
||||
|
||||
expect(standaloneServerFile).toContain(
|
||||
`const logger = options.logger.child({ service: 'test-backend' });`,
|
||||
);
|
||||
expect(standaloneServerFile).toContain(`.addRouter('/test', router);`);
|
||||
|
||||
expect(Task.forCommand).toHaveBeenCalledTimes(2);
|
||||
expect(Task.forCommand).toHaveBeenCalledWith('yarn install', {
|
||||
|
||||
@@ -31,7 +31,8 @@ type Options = {
|
||||
|
||||
export const nodeLibraryPackage = createFactory<Options>({
|
||||
name: 'node-library',
|
||||
description: 'A new node-library package',
|
||||
description:
|
||||
'A new node-library package, exporting shared functionality for backend plugins and modules',
|
||||
optionsDiscovery: async () => ({
|
||||
codeOwnersPath: await getCodeownersFilePath(paths.targetRoot),
|
||||
}),
|
||||
|
||||
@@ -31,7 +31,8 @@ type Options = {
|
||||
|
||||
export const webLibraryPackage = createFactory<Options>({
|
||||
name: 'web-library',
|
||||
description: 'A new web-library package',
|
||||
description:
|
||||
'A new web-library package, exporting shared functionality for frontend plugins',
|
||||
optionsDiscovery: async () => ({
|
||||
codeOwnersPath: await getCodeownersFilePath(paths.targetRoot),
|
||||
}),
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
resolve as resolvePath,
|
||||
relative as relativePath,
|
||||
} from 'path';
|
||||
import pLimit from 'p-limit';
|
||||
import { tmpdir } from 'os';
|
||||
import tar, { CreateOptions, FileOptions } from 'tar';
|
||||
import partition from 'lodash/partition';
|
||||
@@ -102,6 +103,11 @@ type Options = {
|
||||
* command performance.
|
||||
*/
|
||||
alwaysYarnPack?: boolean;
|
||||
|
||||
/**
|
||||
* If set to true, the generated code will be minified.
|
||||
*/
|
||||
minify?: boolean;
|
||||
};
|
||||
|
||||
function prefixLogFunc(prefix: string, out: 'stdout' | 'stderr') {
|
||||
@@ -204,8 +210,7 @@ export async function createDistWorkspace(
|
||||
packageJson: pkg.packageJson,
|
||||
outputs: outputs,
|
||||
logPrefix: `${chalk.cyan(relativePath(paths.targetRoot, pkg.dir))}: `,
|
||||
// No need to detect these for the backend builds, we assume no minification or types
|
||||
minify: false,
|
||||
minify: options.minify,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -352,9 +357,11 @@ async function moveToDistWorkspace(
|
||||
}
|
||||
|
||||
// Repacking in parallel is much faster and safe for all packages outside of the Backstage repo
|
||||
// Limit concurrency to 10 to avoid resource exhaustion on larger monorepos.
|
||||
const limit = pLimit(10);
|
||||
await Promise.all(
|
||||
safePackages.map(async (target, index) =>
|
||||
pack(target, `temp-package-${index}.tgz`),
|
||||
safePackages.map((target, index) =>
|
||||
limit(() => pack(target, `temp-package-${index}.tgz`)),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import { paths } from './paths';
|
||||
import { Lockfile } from './versioning';
|
||||
|
||||
/* eslint-disable @backstage/no-relative-monorepo-imports */
|
||||
|
||||
/*
|
||||
This is a list of all packages used by the templates. If dependencies are added or removed,
|
||||
this list should be updated as well.
|
||||
@@ -33,7 +32,6 @@ This does not create an actual dependency on these packages and does not bring i
|
||||
Rollup will extract the value of the version field in each package at build time without
|
||||
leaving any imports in place.
|
||||
*/
|
||||
|
||||
import { version as backendCommon } from '../../../../packages/backend-common/package.json';
|
||||
import { version as backendPluginApi } from '../../../../packages/backend-plugin-api/package.json';
|
||||
import { version as backendTestUtils } from '../../../../packages/backend-test-utils/package.json';
|
||||
@@ -45,10 +43,14 @@ import { version as corePluginApi } from '../../../../packages/core-plugin-api/p
|
||||
import { version as devUtils } from '../../../../packages/dev-utils/package.json';
|
||||
import { version as testUtils } from '../../../../packages/test-utils/package.json';
|
||||
import { version as scaffolderNode } from '../../../../plugins/scaffolder-node/package.json';
|
||||
import { version as authBackend } from '../../../../plugins/auth-backend/package.json';
|
||||
import { version as authBackendModuleGuestProvider } from '../../../../plugins/auth-backend-module-guest-provider/package.json';
|
||||
import { version as theme } from '../../../../packages/theme/package.json';
|
||||
import { version as backendDefaults } from '../../../../packages/backend-defaults/package.json';
|
||||
|
||||
export const packageVersions: Record<string, string> = {
|
||||
'@backstage/backend-common': backendCommon,
|
||||
'@backstage/backend-defaults': backendDefaults,
|
||||
'@backstage/backend-plugin-api': backendPluginApi,
|
||||
'@backstage/backend-test-utils': backendTestUtils,
|
||||
'@backstage/cli': cli,
|
||||
@@ -60,6 +62,9 @@ export const packageVersions: Record<string, string> = {
|
||||
'@backstage/test-utils': testUtils,
|
||||
'@backstage/theme': theme,
|
||||
'@backstage/plugin-scaffolder-node': scaffolderNode,
|
||||
'@backstage/plugin-auth-backend': authBackend,
|
||||
'@backstage/plugin-auth-backend-module-guest-provider':
|
||||
authBackendModuleGuestProvider,
|
||||
};
|
||||
|
||||
export function findVersion() {
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import { coreServices, createBackendModule } from '@backstage/backend-plugin-api';
|
||||
import {
|
||||
coreServices,
|
||||
createBackendModule,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
|
||||
export const {{moduleVar}} = createBackendModule({
|
||||
pluginId: '{{pluginId}}',
|
||||
@@ -7,7 +10,7 @@ export const {{moduleVar}} = createBackendModule({
|
||||
reg.registerInit({
|
||||
deps: { logger: coreServices.logger },
|
||||
async init({ logger }) {
|
||||
logger.info('Hello World!')
|
||||
logger.info('Hello World!');
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
@@ -7,7 +7,7 @@ _This plugin was created through the Backstage CLI_
|
||||
## Getting started
|
||||
|
||||
Your plugin has been added to the example app in this repository, meaning you'll be able to access it by running `yarn
|
||||
start` in the root directory, and then navigating to [/{{id}}](http://localhost:3000/{{id}}).
|
||||
start` in the root directory, and then navigating to [/{{pluginVar}}/health](http://localhost:7007/api/{{pluginVar}}/health).
|
||||
|
||||
You can also serve the plugin in isolation by running `yarn start` in the plugin directory.
|
||||
This method of serving the plugin provides quicker iteration speed and a faster startup and hot reloads.
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import { createBackend } from '@backstage/backend-defaults';
|
||||
|
||||
const backend = createBackend();
|
||||
|
||||
backend.add(import('@backstage/plugin-auth-backend'));
|
||||
backend.add(import('@backstage/plugin-auth-backend-module-guest-provider'));
|
||||
backend.add(import('../src'));
|
||||
|
||||
backend.start();
|
||||
@@ -29,6 +29,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/backend-common": "{{versionQuery '@backstage/backend-common'}}",
|
||||
"@backstage/backend-defaults": "{{versionQuery '@backstage/backend-defaults'}}",
|
||||
"@backstage/backend-plugin-api": "{{versionQuery '@backstage/backend-plugin-api'}}",
|
||||
"@backstage/config": "{{versionQuery '@backstage/config'}}",
|
||||
"@types/express": "{{versionQuery '@types/express' '4.17.6'}}",
|
||||
"express": "{{versionQuery 'express' '4.17.1'}}",
|
||||
@@ -39,6 +41,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "{{versionQuery '@backstage/cli'}}",
|
||||
"@backstage/plugin-auth-backend": "{{versionQuery '@backstage/plugin-auth-backend'}}",
|
||||
"@backstage/plugin-auth-backend-module-guest-provider": "{{versionQuery '@backstage/plugin-auth-backend-module-guest-provider'}}",
|
||||
"@types/supertest": "{{versionQuery '@types/supertest' '2.0.12'}}",
|
||||
"supertest": "{{versionQuery 'supertest' '6.2.4'}}",
|
||||
"msw": "{{versionQuery 'msw' '1.0.0'}}"
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export * from './service/router';
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './service/router';
|
||||
export { {{pluginVar}} as default } from './plugin';
|
||||
@@ -0,0 +1,36 @@
|
||||
import {
|
||||
coreServices,
|
||||
createBackendPlugin,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { createRouter } from './service/router';
|
||||
|
||||
/**
|
||||
* {{pluginVar}} backend plugin
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const {{pluginVar}} = createBackendPlugin({
|
||||
pluginId: '{{pluginVar}}',
|
||||
register(env) {
|
||||
env.registerInit({
|
||||
deps: {
|
||||
httpRouter: coreServices.httpRouter,
|
||||
logger: coreServices.logger,
|
||||
},
|
||||
async init({
|
||||
httpRouter,
|
||||
logger,
|
||||
}) {
|
||||
httpRouter.use(
|
||||
await createRouter({
|
||||
logger,
|
||||
}),
|
||||
);
|
||||
httpRouter.addAuthPolicy({
|
||||
path: '/health',
|
||||
allow: 'unauthenticated',
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -1,17 +0,0 @@
|
||||
import { getRootLogger } from '@backstage/backend-common';
|
||||
import yn from 'yn';
|
||||
import { startStandaloneServer } from './service/standaloneServer';
|
||||
|
||||
const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7007;
|
||||
const enableCors = yn(process.env.PLUGIN_CORS, { default: false });
|
||||
const logger = getRootLogger();
|
||||
|
||||
startStandaloneServer({ port, enableCors, logger }).catch(err => {
|
||||
logger.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
process.on('SIGINT', () => {
|
||||
logger.info('CTRL+C pressed; exiting.');
|
||||
process.exit(0);
|
||||
});
|
||||
@@ -1,10 +1,10 @@
|
||||
import { errorHandler } from '@backstage/backend-common';
|
||||
import { LoggerService } from '@backstage/backend-plugin-api';
|
||||
import express from 'express';
|
||||
import Router from 'express-promise-router';
|
||||
import { Logger } from 'winston';
|
||||
|
||||
export interface RouterOptions {
|
||||
logger: Logger;
|
||||
logger: LoggerService;
|
||||
}
|
||||
|
||||
export async function createRouter(
|
||||
@@ -19,6 +19,7 @@ export async function createRouter(
|
||||
logger.info('PONG!');
|
||||
response.json({ status: 'ok' });
|
||||
});
|
||||
|
||||
router.use(errorHandler());
|
||||
return router;
|
||||
}
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
import { createServiceBuilder } from '@backstage/backend-common';
|
||||
import { Server } from 'http';
|
||||
import { Logger } from 'winston';
|
||||
import { createRouter } from './router';
|
||||
|
||||
export interface ServerOptions {
|
||||
port: number;
|
||||
enableCors: boolean;
|
||||
logger: Logger;
|
||||
}
|
||||
|
||||
export async function startStandaloneServer(
|
||||
options: ServerOptions,
|
||||
): Promise<Server> {
|
||||
const logger = options.logger.child({ service: '{{id}}-backend' });
|
||||
logger.debug('Starting application server...');
|
||||
const router = await createRouter({
|
||||
logger,
|
||||
});
|
||||
|
||||
let service = createServiceBuilder(module)
|
||||
.setPort(options.port)
|
||||
.addRouter('/{{id}}', router);
|
||||
if (options.enableCors) {
|
||||
service = service.enableCors({ origin: 'http://localhost:3000' });
|
||||
}
|
||||
|
||||
return await service.start().catch(err => {
|
||||
logger.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
module.hot?.accept();
|
||||
@@ -10,10 +10,10 @@
|
||||
* between the frontend and backend plugin packages.
|
||||
*/
|
||||
export type CommonType = {
|
||||
field: string
|
||||
}
|
||||
field: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Or you might declare some common constants.
|
||||
*/
|
||||
export const COMMON_CONSTANT = 1
|
||||
export const COMMON_CONSTANT = 1;
|
||||
|
||||
@@ -7,6 +7,6 @@ createDevApp()
|
||||
.addPage({
|
||||
element: <{{ extensionName }} />,
|
||||
title: 'Root Page',
|
||||
path: '/{{ id }}'
|
||||
path: '/{{ id }}',
|
||||
})
|
||||
.render();
|
||||
|
||||
+4
-2
@@ -6,7 +6,7 @@ import { screen } from '@testing-library/react';
|
||||
import {
|
||||
setupRequestMockHandlers,
|
||||
renderInTestApp,
|
||||
} from "@backstage/test-utils";
|
||||
} from '@backstage/test-utils';
|
||||
|
||||
describe('ExampleComponent', () => {
|
||||
const server = setupServer();
|
||||
@@ -22,6 +22,8 @@ describe('ExampleComponent', () => {
|
||||
|
||||
it('should render', async () => {
|
||||
await renderInTestApp(<ExampleComponent />);
|
||||
expect(screen.getByText('Welcome to {{ id }}!')).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText('Welcome to {{ id }}!'),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
+2
-2
@@ -8,7 +8,7 @@ describe('ExampleFetchComponent', () => {
|
||||
|
||||
// Wait for the table to render
|
||||
const table = await screen.findByRole('table');
|
||||
const nationality = screen.getAllByText("GB")
|
||||
const nationality = screen.getAllByText('GB')
|
||||
// Assert that the table contains the expected user data
|
||||
expect(table).toBeInTheDocument();
|
||||
expect(screen.getByAltText('Carolyn')).toBeInTheDocument();
|
||||
@@ -16,4 +16,4 @@ describe('ExampleFetchComponent', () => {
|
||||
expect(screen.getByText('carolyn.moore@example.com')).toBeInTheDocument();
|
||||
expect(nationality[0]).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+170
-165
@@ -1,232 +1,237 @@
|
||||
import React from 'react';
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import { Table, TableColumn, Progress, ResponseErrorPanel } from '@backstage/core-components';
|
||||
import {
|
||||
Table,
|
||||
TableColumn,
|
||||
Progress,
|
||||
ResponseErrorPanel,
|
||||
} from '@backstage/core-components';
|
||||
import useAsync from 'react-use/lib/useAsync';
|
||||
|
||||
export const exampleUsers = {
|
||||
"results": [
|
||||
results: [
|
||||
{
|
||||
"gender": "female",
|
||||
"name": {
|
||||
"title": "Miss",
|
||||
"first": "Carolyn",
|
||||
"last": "Moore"
|
||||
gender: 'female',
|
||||
name: {
|
||||
title: 'Miss',
|
||||
first: 'Carolyn',
|
||||
last: 'Moore',
|
||||
},
|
||||
"email": "carolyn.moore@example.com",
|
||||
"picture": "https://api.dicebear.com/6.x/open-peeps/svg?seed=Carolyn",
|
||||
"nat": "GB"
|
||||
email: 'carolyn.moore@example.com',
|
||||
picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Carolyn',
|
||||
nat: 'GB',
|
||||
},
|
||||
{
|
||||
"gender": "female",
|
||||
"name": {
|
||||
"title": "Ms",
|
||||
"first": "Esma",
|
||||
"last": "Berberoğlu"
|
||||
gender: 'female',
|
||||
name: {
|
||||
title: 'Ms',
|
||||
first: 'Esma',
|
||||
last: 'Berberoğlu',
|
||||
},
|
||||
"email": "esma.berberoglu@example.com",
|
||||
"picture": "https://api.dicebear.com/6.x/open-peeps/svg?seed=Esma",
|
||||
"nat": "TR"
|
||||
email: 'esma.berberoglu@example.com',
|
||||
picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Esma',
|
||||
nat: 'TR',
|
||||
},
|
||||
{
|
||||
"gender": "female",
|
||||
"name": {
|
||||
"title": "Ms",
|
||||
"first": "Isabella",
|
||||
"last": "Rhodes"
|
||||
gender: 'female',
|
||||
name: {
|
||||
title: 'Ms',
|
||||
first: 'Isabella',
|
||||
last: 'Rhodes',
|
||||
},
|
||||
"email": "isabella.rhodes@example.com",
|
||||
"picture": "https://api.dicebear.com/6.x/open-peeps/svg?seed=Isabella",
|
||||
"nat": "GB"
|
||||
email: 'isabella.rhodes@example.com',
|
||||
picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Isabella',
|
||||
nat: 'GB',
|
||||
},
|
||||
{
|
||||
"gender": "male",
|
||||
"name": {
|
||||
"title": "Mr",
|
||||
"first": "Derrick",
|
||||
"last": "Carter"
|
||||
gender: 'male',
|
||||
name: {
|
||||
title: 'Mr',
|
||||
first: 'Derrick',
|
||||
last: 'Carter',
|
||||
},
|
||||
"email": "derrick.carter@example.com",
|
||||
"picture": "https://api.dicebear.com/6.x/open-peeps/svg?seed=Derrick",
|
||||
"nat": "IE"
|
||||
email: 'derrick.carter@example.com',
|
||||
picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Derrick',
|
||||
nat: 'IE',
|
||||
},
|
||||
{
|
||||
"gender": "female",
|
||||
"name": {
|
||||
"title": "Miss",
|
||||
"first": "Mattie",
|
||||
"last": "Lambert"
|
||||
gender: 'female',
|
||||
name: {
|
||||
title: 'Miss',
|
||||
first: 'Mattie',
|
||||
last: 'Lambert',
|
||||
},
|
||||
"email": "mattie.lambert@example.com",
|
||||
"picture": "https://api.dicebear.com/6.x/open-peeps/svg?seed=Mattie",
|
||||
"nat": "AU"
|
||||
email: 'mattie.lambert@example.com',
|
||||
picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Mattie',
|
||||
nat: 'AU',
|
||||
},
|
||||
{
|
||||
"gender": "male",
|
||||
"name": {
|
||||
"title": "Mr",
|
||||
"first": "Mijat",
|
||||
"last": "Rakić"
|
||||
gender: 'male',
|
||||
name: {
|
||||
title: 'Mr',
|
||||
first: 'Mijat',
|
||||
last: 'Rakić',
|
||||
},
|
||||
"email": "mijat.rakic@example.com",
|
||||
"picture": "https://api.dicebear.com/6.x/open-peeps/svg?seed=Mijat",
|
||||
"nat": "RS"
|
||||
email: 'mijat.rakic@example.com',
|
||||
picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Mijat',
|
||||
nat: 'RS',
|
||||
},
|
||||
{
|
||||
"gender": "male",
|
||||
"name": {
|
||||
"title": "Mr",
|
||||
"first": "Javier",
|
||||
"last": "Reid"
|
||||
gender: 'male',
|
||||
name: {
|
||||
title: 'Mr',
|
||||
first: 'Javier',
|
||||
last: 'Reid',
|
||||
},
|
||||
"email": "javier.reid@example.com",
|
||||
"picture": "https://api.dicebear.com/6.x/open-peeps/svg?seed=Javier",
|
||||
"nat": "US"
|
||||
email: 'javier.reid@example.com',
|
||||
picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Javier',
|
||||
nat: 'US',
|
||||
},
|
||||
{
|
||||
"gender": "female",
|
||||
"name": {
|
||||
"title": "Ms",
|
||||
"first": "Isabella",
|
||||
"last": "Li"
|
||||
gender: 'female',
|
||||
name: {
|
||||
title: 'Ms',
|
||||
first: 'Isabella',
|
||||
last: 'Li',
|
||||
},
|
||||
"email": "isabella.li@example.com",
|
||||
"picture": "https://api.dicebear.com/6.x/open-peeps/svg?seed=Isabella",
|
||||
"nat": "CA"
|
||||
email: 'isabella.li@example.com',
|
||||
picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Isabella',
|
||||
nat: 'CA',
|
||||
},
|
||||
{
|
||||
"gender": "female",
|
||||
"name": {
|
||||
"title": "Mrs",
|
||||
"first": "Stephanie",
|
||||
"last": "Garrett"
|
||||
gender: 'female',
|
||||
name: {
|
||||
title: 'Mrs',
|
||||
first: 'Stephanie',
|
||||
last: 'Garrett',
|
||||
},
|
||||
"email": "stephanie.garrett@example.com",
|
||||
"picture": "https://api.dicebear.com/6.x/open-peeps/svg?seed=Stephanie",
|
||||
"nat": "AU"
|
||||
email: 'stephanie.garrett@example.com',
|
||||
picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Stephanie',
|
||||
nat: 'AU',
|
||||
},
|
||||
{
|
||||
"gender": "female",
|
||||
"name": {
|
||||
"title": "Ms",
|
||||
"first": "Antonia",
|
||||
"last": "Núñez"
|
||||
gender: 'female',
|
||||
name: {
|
||||
title: 'Ms',
|
||||
first: 'Antonia',
|
||||
last: 'Núñez',
|
||||
},
|
||||
"email": "antonia.nunez@example.com",
|
||||
"picture": "https://api.dicebear.com/6.x/open-peeps/svg?seed=Antonia",
|
||||
"nat": "ES"
|
||||
email: 'antonia.nunez@example.com',
|
||||
picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Antonia',
|
||||
nat: 'ES',
|
||||
},
|
||||
{
|
||||
"gender": "male",
|
||||
"name": {
|
||||
"title": "Mr",
|
||||
"first": "Donald",
|
||||
"last": "Young"
|
||||
gender: 'male',
|
||||
name: {
|
||||
title: 'Mr',
|
||||
first: 'Donald',
|
||||
last: 'Young',
|
||||
},
|
||||
"email": "donald.young@example.com",
|
||||
"picture": "https://api.dicebear.com/6.x/open-peeps/svg?seed=Donald",
|
||||
"nat": "US"
|
||||
email: 'donald.young@example.com',
|
||||
picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Donald',
|
||||
nat: 'US',
|
||||
},
|
||||
{
|
||||
"gender": "male",
|
||||
"name": {
|
||||
"title": "Mr",
|
||||
"first": "Iegor",
|
||||
"last": "Holodovskiy"
|
||||
gender: 'male',
|
||||
name: {
|
||||
title: 'Mr',
|
||||
first: 'Iegor',
|
||||
last: 'Holodovskiy',
|
||||
},
|
||||
"email": "iegor.holodovskiy@example.com",
|
||||
"picture": "https://api.dicebear.com/6.x/open-peeps/svg?seed=Iegor",
|
||||
"nat": "UA"
|
||||
email: 'iegor.holodovskiy@example.com',
|
||||
picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Iegor',
|
||||
nat: 'UA',
|
||||
},
|
||||
{
|
||||
"gender": "female",
|
||||
"name": {
|
||||
"title": "Madame",
|
||||
"first": "Jessica",
|
||||
"last": "David"
|
||||
gender: 'female',
|
||||
name: {
|
||||
title: 'Madame',
|
||||
first: 'Jessica',
|
||||
last: 'David',
|
||||
},
|
||||
"email": "jessica.david@example.com",
|
||||
"picture": "https://api.dicebear.com/6.x/open-peeps/svg?seed=Jessica",
|
||||
"nat": "CH"
|
||||
email: 'jessica.david@example.com',
|
||||
picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Jessica',
|
||||
nat: 'CH',
|
||||
},
|
||||
{
|
||||
"gender": "female",
|
||||
"name": {
|
||||
"title": "Ms",
|
||||
"first": "Eve",
|
||||
"last": "Martinez"
|
||||
gender: 'female',
|
||||
name: {
|
||||
title: 'Ms',
|
||||
first: 'Eve',
|
||||
last: 'Martinez',
|
||||
},
|
||||
"email": "eve.martinez@example.com",
|
||||
"picture": "https://api.dicebear.com/6.x/open-peeps/svg?seed=Eve",
|
||||
"nat": "FR"
|
||||
email: 'eve.martinez@example.com',
|
||||
picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Eve',
|
||||
nat: 'FR',
|
||||
},
|
||||
{
|
||||
"gender": "male",
|
||||
"name": {
|
||||
"title": "Mr",
|
||||
"first": "Caleb",
|
||||
"last": "Silva"
|
||||
gender: 'male',
|
||||
name: {
|
||||
title: 'Mr',
|
||||
first: 'Caleb',
|
||||
last: 'Silva',
|
||||
},
|
||||
"email": "caleb.silva@example.com",
|
||||
"picture": "https://api.dicebear.com/6.x/open-peeps/svg?seed=Caleb",
|
||||
"nat": "US"
|
||||
email: 'caleb.silva@example.com',
|
||||
picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Caleb',
|
||||
nat: 'US',
|
||||
},
|
||||
{
|
||||
"gender": "female",
|
||||
"name": {
|
||||
"title": "Miss",
|
||||
"first": "Marcia",
|
||||
"last": "Jenkins"
|
||||
gender: 'female',
|
||||
name: {
|
||||
title: 'Miss',
|
||||
first: 'Marcia',
|
||||
last: 'Jenkins',
|
||||
},
|
||||
"email": "marcia.jenkins@example.com",
|
||||
"picture": "https://api.dicebear.com/6.x/open-peeps/svg?seed=Marcia",
|
||||
"nat": "US"
|
||||
email: 'marcia.jenkins@example.com',
|
||||
picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Marcia',
|
||||
nat: 'US',
|
||||
},
|
||||
{
|
||||
"gender": "female",
|
||||
"name": {
|
||||
"title": "Mrs",
|
||||
"first": "Mackenzie",
|
||||
"last": "Jones"
|
||||
gender: 'female',
|
||||
name: {
|
||||
title: 'Mrs',
|
||||
first: 'Mackenzie',
|
||||
last: 'Jones',
|
||||
},
|
||||
"email": "mackenzie.jones@example.com",
|
||||
"picture": "https://api.dicebear.com/6.x/open-peeps/svg?seed=Mackenzie",
|
||||
"nat": "NZ"
|
||||
email: 'mackenzie.jones@example.com',
|
||||
picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Mackenzie',
|
||||
nat: 'NZ',
|
||||
},
|
||||
{
|
||||
"gender": "male",
|
||||
"name": {
|
||||
"title": "Mr",
|
||||
"first": "Jeremiah",
|
||||
"last": "Gutierrez"
|
||||
gender: 'male',
|
||||
name: {
|
||||
title: 'Mr',
|
||||
first: 'Jeremiah',
|
||||
last: 'Gutierrez',
|
||||
},
|
||||
"email": "jeremiah.gutierrez@example.com",
|
||||
"picture": "https://api.dicebear.com/6.x/open-peeps/svg?seed=Jeremiah",
|
||||
"nat": "AU"
|
||||
email: 'jeremiah.gutierrez@example.com',
|
||||
picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Jeremiah',
|
||||
nat: 'AU',
|
||||
},
|
||||
{
|
||||
"gender": "female",
|
||||
"name": {
|
||||
"title": "Ms",
|
||||
"first": "Luciara",
|
||||
"last": "Souza"
|
||||
gender: 'female',
|
||||
name: {
|
||||
title: 'Ms',
|
||||
first: 'Luciara',
|
||||
last: 'Souza',
|
||||
},
|
||||
"email": "luciara.souza@example.com",
|
||||
"picture": "https://api.dicebear.com/6.x/open-peeps/svg?seed=Luciara",
|
||||
"nat": "BR"
|
||||
email: 'luciara.souza@example.com',
|
||||
picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Luciara',
|
||||
nat: 'BR',
|
||||
},
|
||||
{
|
||||
"gender": "male",
|
||||
"name": {
|
||||
"title": "Mr",
|
||||
"first": "Valgi",
|
||||
"last": "da Cunha"
|
||||
gender: 'male',
|
||||
name: {
|
||||
title: 'Mr',
|
||||
first: 'Valgi',
|
||||
last: 'da Cunha',
|
||||
},
|
||||
"email": "valgi.dacunha@example.com",
|
||||
"picture": "https://api.dicebear.com/6.x/open-peeps/svg?seed=Valgi",
|
||||
"nat": "BR"
|
||||
}
|
||||
]
|
||||
}
|
||||
email: 'valgi.dacunha@example.com',
|
||||
picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Valgi',
|
||||
nat: 'BR',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const useStyles = makeStyles({
|
||||
avatar: {
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import { createPlugin, createRoutableExtension } from '@backstage/core-plugin-api';
|
||||
import {
|
||||
createPlugin,
|
||||
createRoutableExtension,
|
||||
} from '@backstage/core-plugin-api';
|
||||
|
||||
import { rootRouteRef } from './routes';
|
||||
|
||||
|
||||
+4
-4
@@ -5,14 +5,14 @@ import { ExampleComponent } from './ExampleComponent';
|
||||
|
||||
describe('ExampleComponent', () => {
|
||||
it('should render', async () => {
|
||||
await renderInTestApp(<ExampleComponent />)
|
||||
await renderInTestApp(<ExampleComponent />);
|
||||
|
||||
expect(screen.getByText('Hello World')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should display a custom message', async () => {
|
||||
await renderInTestApp(<ExampleComponent message={'Hello Example'} />)
|
||||
await renderInTestApp(<ExampleComponent message="Hello Example" />);
|
||||
|
||||
expect(screen.getByText('Hello Example')).toBeInTheDocument();
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
+1
-1
@@ -11,5 +11,5 @@ export function useExample() {
|
||||
|
||||
useEffect(() => {
|
||||
alertApi.post({ message: 'Hello World!' });
|
||||
}, [alertApi])
|
||||
}, [alertApi]);
|
||||
}
|
||||
|
||||
@@ -8,5 +8,5 @@
|
||||
// In this package you might for example export components or hooks
|
||||
// that are useful to other plugins or modules.
|
||||
|
||||
export * from './components'
|
||||
export * from './hooks'
|
||||
export * from './components';
|
||||
export * from './hooks';
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Backstage is an open platform for building developer portals"
|
||||
content="Backstage is an open source framework for building developer portals"
|
||||
/>
|
||||
<title>Backstage</title>
|
||||
</head>
|
||||
|
||||
Reference in New Issue
Block a user