@backstage/cli 0.28.0-next.2 → 0.29.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/CHANGELOG.md +95 -0
  2. package/config/jest.js +49 -25
  3. package/config/jestRejectNetworkRequests.js +59 -0
  4. package/config/nodeTransform.cjs +33 -0
  5. package/dist/commands/build/buildFrontend.cjs.js +11 -13
  6. package/dist/commands/build/command.cjs.js +5 -2
  7. package/dist/commands/buildWorkspace.cjs.js +1 -1
  8. package/dist/commands/index.cjs.js +9 -3
  9. package/dist/commands/repo/lint.cjs.js +23 -33
  10. package/dist/commands/repo/test.cjs.js +13 -32
  11. package/dist/commands/start/command.cjs.js +1 -0
  12. package/dist/commands/start/startBackend.cjs.js +23 -92
  13. package/dist/commands/start/startFrontend.cjs.js +6 -8
  14. package/dist/commands/versions/bump.cjs.js +9 -3
  15. package/dist/lib/bundler/bundle.cjs.js +5 -4
  16. package/dist/lib/bundler/config.cjs.js +75 -171
  17. package/dist/lib/bundler/hasReactDomClient.cjs.js +5 -1
  18. package/dist/lib/bundler/linkWorkspaces.cjs.js +31 -0
  19. package/dist/lib/bundler/optimization.cjs.js +10 -6
  20. package/dist/lib/bundler/server.cjs.js +47 -7
  21. package/dist/lib/bundler/transforms.cjs.js +7 -6
  22. package/dist/lib/cache/SuccessCache.cjs.js +70 -0
  23. package/dist/lib/packager/createDistWorkspace.cjs.js +3 -3
  24. package/dist/lib/{experimental/startBackendExperimental.cjs.js → runner/runBackend.cjs.js} +6 -5
  25. package/dist/lib/version.cjs.js +30 -22
  26. package/dist/packages/backend-defaults/package.json.cjs.js +1 -1
  27. package/dist/packages/backend-plugin-api/package.json.cjs.js +1 -1
  28. package/dist/packages/backend-test-utils/package.json.cjs.js +1 -1
  29. package/dist/packages/catalog-client/package.json.cjs.js +6 -0
  30. package/dist/packages/cli/package.json.cjs.js +15 -5
  31. package/dist/packages/core-app-api/package.json.cjs.js +1 -1
  32. package/dist/packages/core-components/package.json.cjs.js +1 -1
  33. package/dist/packages/core-plugin-api/package.json.cjs.js +1 -1
  34. package/dist/packages/dev-utils/package.json.cjs.js +1 -1
  35. package/dist/packages/errors/package.json.cjs.js +6 -0
  36. package/dist/packages/test-utils/package.json.cjs.js +1 -1
  37. package/dist/packages/theme/package.json.cjs.js +1 -1
  38. package/dist/plugins/auth-backend/package.json.cjs.js +1 -1
  39. package/dist/plugins/auth-backend-module-guest-provider/package.json.cjs.js +1 -1
  40. package/dist/plugins/catalog-node/package.json.cjs.js +6 -0
  41. package/dist/plugins/scaffolder-node/package.json.cjs.js +1 -1
  42. package/dist/plugins/scaffolder-node-test-utils/package.json.cjs.js +6 -0
  43. package/package.json +45 -19
  44. package/templates/default-backend-plugin/README.md.hbs +22 -8
  45. package/templates/default-backend-plugin/dev/index.ts.hbs +60 -0
  46. package/templates/default-backend-plugin/package.json.hbs +5 -5
  47. package/templates/default-backend-plugin/src/index.ts.hbs +0 -1
  48. package/templates/default-backend-plugin/src/plugin.test.ts.hbs +85 -0
  49. package/templates/default-backend-plugin/src/plugin.ts.hbs +16 -14
  50. package/templates/default-backend-plugin/src/router.test.ts +67 -0
  51. package/templates/default-backend-plugin/src/router.ts +51 -0
  52. package/templates/default-backend-plugin/src/services/TodoListService/createTodoListService.ts +100 -0
  53. package/templates/default-backend-plugin/src/services/TodoListService/index.ts +1 -0
  54. package/templates/default-backend-plugin/src/services/TodoListService/types.ts +27 -0
  55. package/templates/scaffolder-module/package.json.hbs +3 -1
  56. package/templates/scaffolder-module/src/actions/example.test.ts +24 -0
  57. package/templates/scaffolder-module/src/actions/{example/example.ts → example.ts} +7 -3
  58. package/templates/scaffolder-module/src/index.ts.hbs +1 -1
  59. package/templates/scaffolder-module/src/{actions/example/module.ts → module.ts} +3 -3
  60. package/dist/lib/bundler/LinkedPackageResolvePlugin.cjs.js +0 -47
  61. package/dist/lib/bundler/backend.cjs.js +0 -36
  62. package/templates/default-backend-plugin/dev/index.ts +0 -9
  63. package/templates/default-backend-plugin/src/service/router.test.ts +0 -30
  64. package/templates/default-backend-plugin/src/service/router.ts +0 -28
  65. package/templates/scaffolder-module/src/actions/example/example.test.ts +0 -32
  66. package/templates/scaffolder-module/src/actions/example/index.ts +0 -7
  67. package/templates/scaffolder-module/src/actions/index.ts +0 -1
  68. /package/dist/lib/{experimental → ipc}/IpcServer.cjs.js +0 -0
  69. /package/dist/lib/{experimental → ipc}/ServerDataStore.cjs.js +0 -0
@@ -30,19 +30,19 @@
30
30
  "dependencies": {
31
31
  "@backstage/backend-defaults": "{{versionQuery '@backstage/backend-defaults'}}",
32
32
  "@backstage/backend-plugin-api": "{{versionQuery '@backstage/backend-plugin-api'}}",
33
+ "@backstage/catalog-client": "{{versionQuery '@backstage/catalog-client'}}",
34
+ "@backstage/errors": "{{versionQuery '@backstage/errors'}}",
35
+ "@backstage/plugin-catalog-node": "{{versionQuery '@backstage/plugin-catalog-node'}}",
33
36
  "express": "{{versionQuery 'express' '4.17.1'}}",
34
37
  "express-promise-router": "{{versionQuery 'express-promise-router' '4.1.0'}}",
35
- "node-fetch": "{{versionQuery 'node-fetch' '2.6.7'}}"
38
+ "zod": "{{versionQuery 'zod' '3.22.4'}}"
36
39
  },
37
40
  "devDependencies": {
38
41
  "@backstage/backend-test-utils": "{{versionQuery '@backstage/backend-test-utils'}}",
39
42
  "@backstage/cli": "{{versionQuery '@backstage/cli'}}",
40
- "@backstage/plugin-auth-backend": "{{versionQuery '@backstage/plugin-auth-backend'}}",
41
- "@backstage/plugin-auth-backend-module-guest-provider": "{{versionQuery '@backstage/plugin-auth-backend-module-guest-provider'}}",
42
43
  "@types/express": "{{versionQuery '@types/express' '4.17.6'}}",
43
44
  "@types/supertest": "{{versionQuery '@types/supertest' '2.0.12'}}",
44
- "supertest": "{{versionQuery 'supertest' '6.2.4'}}",
45
- "msw": "{{versionQuery 'msw' '2.3.1'}}"
45
+ "supertest": "{{versionQuery 'supertest' '6.2.4'}}"
46
46
  },
47
47
  "files": [
48
48
  "dist"
@@ -1,2 +1 @@
1
- export * from './service/router';
2
1
  export { {{pluginVar}} as default } from './plugin';
@@ -0,0 +1,85 @@
1
+ import {
2
+ mockCredentials,
3
+ startTestBackend,
4
+ } from '@backstage/backend-test-utils';
5
+ import { {{pluginVar}} } from './plugin';
6
+ import request from 'supertest';
7
+ import { catalogServiceMock } from '@backstage/plugin-catalog-node/testUtils';
8
+
9
+ // TEMPLATE NOTE:
10
+ // Plugin tests are integration tests for your plugin, ensuring that all pieces
11
+ // work together end-to-end. You can still mock injected backend services
12
+ // however, just like anyone who installs your plugin might replace the
13
+ // services with their own implementations.
14
+ describe('plugin', () => {
15
+ it('should create and read TODO items', async () => {
16
+ const { server } = await startTestBackend({
17
+ features: [{{pluginVar}}],
18
+ });
19
+
20
+ await request(server).get('/api/{{id}}/todos').expect(200, {
21
+ items: [],
22
+ });
23
+
24
+ const createRes = await request(server)
25
+ .post('/api/{{id}}/todos')
26
+ .send({ title: 'My Todo' });
27
+
28
+ expect(createRes.status).toBe(201);
29
+ expect(createRes.body).toEqual({
30
+ id: expect.any(String),
31
+ title: 'My Todo',
32
+ createdBy: mockCredentials.user().principal.userEntityRef,
33
+ createdAt: expect.any(String),
34
+ });
35
+
36
+ const createdTodoItem = createRes.body;
37
+
38
+ await request(server)
39
+ .get('/api/{{id}}/todos')
40
+ .expect(200, {
41
+ items: [createdTodoItem],
42
+ });
43
+
44
+ await request(server)
45
+ .get(`/api/{{id}}/todos/${createdTodoItem.id}`)
46
+ .expect(200, createdTodoItem);
47
+ });
48
+
49
+ it('should create TODO item with catalog information', async () => {
50
+ const { server } = await startTestBackend({
51
+ features: [
52
+ {{pluginVar}},
53
+ catalogServiceMock.factory({
54
+ entities: [
55
+ {
56
+ apiVersion: 'backstage.io/v1alpha1',
57
+ kind: 'Component',
58
+ metadata: {
59
+ name: 'my-component',
60
+ namespace: 'default',
61
+ title: 'My Component',
62
+ },
63
+ spec: {
64
+ type: 'service',
65
+ owner: 'me',
66
+ },
67
+ },
68
+ ],
69
+ }),
70
+ ],
71
+ });
72
+
73
+ const createRes = await request(server)
74
+ .post('/api/{{id}}/todos')
75
+ .send({ title: 'My Todo', entityRef: 'component:default/my-component' });
76
+
77
+ expect(createRes.status).toBe(201);
78
+ expect(createRes.body).toEqual({
79
+ id: expect.any(String),
80
+ title: '[My Component] My Todo',
81
+ createdBy: mockCredentials.user().principal.userEntityRef,
82
+ createdAt: expect.any(String),
83
+ });
84
+ });
85
+ });
@@ -2,7 +2,9 @@ import {
2
2
  coreServices,
3
3
  createBackendPlugin,
4
4
  } from '@backstage/backend-plugin-api';
5
- import { createRouter } from './service/router';
5
+ import { createRouter } from './router';
6
+ import { catalogServiceRef } from '@backstage/plugin-catalog-node/alpha';
7
+ import { createTodoListService } from './services/TodoListService';
6
8
 
7
9
  /**
8
10
  * {{pluginVar}} backend plugin
@@ -14,25 +16,25 @@ export const {{pluginVar}} = createBackendPlugin({
14
16
  register(env) {
15
17
  env.registerInit({
16
18
  deps: {
17
- httpRouter: coreServices.httpRouter,
18
19
  logger: coreServices.logger,
19
- config: coreServices.rootConfig,
20
+ auth: coreServices.auth,
21
+ httpAuth: coreServices.httpAuth,
22
+ httpRouter: coreServices.httpRouter,
23
+ catalog: catalogServiceRef,
20
24
  },
21
- async init({
22
- httpRouter,
23
- logger,
24
- config,
25
- }) {
25
+ async init({ logger, auth, httpAuth, httpRouter, catalog }) {
26
+ const todoListService = await createTodoListService({
27
+ logger,
28
+ auth,
29
+ catalog,
30
+ });
31
+
26
32
  httpRouter.use(
27
33
  await createRouter({
28
- logger,
29
- config,
34
+ httpAuth,
35
+ todoListService,
30
36
  }),
31
37
  );
32
- httpRouter.addAuthPolicy({
33
- path: '/health',
34
- allow: 'unauthenticated',
35
- });
36
38
  },
37
39
  });
38
40
  },
@@ -0,0 +1,67 @@
1
+ import {
2
+ mockCredentials,
3
+ mockErrorHandler,
4
+ mockServices,
5
+ } from '@backstage/backend-test-utils';
6
+ import express from 'express';
7
+ import request from 'supertest';
8
+
9
+ import { createRouter } from './router';
10
+ import { TodoListService } from './services/TodoListService/types';
11
+
12
+ const mockTodoItem = {
13
+ title: 'Do the thing',
14
+ id: '123',
15
+ createdBy: mockCredentials.user().principal.userEntityRef,
16
+ createdAt: new Date().toISOString(),
17
+ };
18
+
19
+ // TEMPLATE NOTE:
20
+ // Testing the router directly allows you to write a unit test that mocks the provided options.
21
+ describe('createRouter', () => {
22
+ let app: express.Express;
23
+ let todoListService: jest.Mocked<TodoListService>;
24
+
25
+ beforeEach(async () => {
26
+ todoListService = {
27
+ createTodo: jest.fn(),
28
+ listTodos: jest.fn(),
29
+ getTodo: jest.fn(),
30
+ };
31
+ const router = await createRouter({
32
+ httpAuth: mockServices.httpAuth(),
33
+ todoListService,
34
+ });
35
+ app = express();
36
+ app.use(router);
37
+ app.use(mockErrorHandler());
38
+ });
39
+
40
+ it('should create a TODO', async () => {
41
+ todoListService.createTodo.mockResolvedValue(mockTodoItem);
42
+
43
+ const response = await request(app).post('/todos').send({
44
+ title: 'Do the thing',
45
+ });
46
+
47
+ expect(response.status).toBe(201);
48
+ expect(response.body).toEqual(mockTodoItem);
49
+ });
50
+
51
+ it('should not allow unauthenticated requests to create a TODO', async () => {
52
+ todoListService.createTodo.mockResolvedValue(mockTodoItem);
53
+
54
+ // TEMPLATE NOTE:
55
+ // The HttpAuth mock service considers all requests to be authenticated as a
56
+ // mock user by default. In order to test other cases we need to explicitly
57
+ // pass an authorization header with mock credentials.
58
+ const response = await request(app)
59
+ .post('/todos')
60
+ .set('Authorization', mockCredentials.none.header())
61
+ .send({
62
+ title: 'Do the thing',
63
+ });
64
+
65
+ expect(response.status).toBe(401);
66
+ });
67
+ });
@@ -0,0 +1,51 @@
1
+ import { HttpAuthService } from '@backstage/backend-plugin-api';
2
+ import { InputError } from '@backstage/errors';
3
+ import { z } from 'zod';
4
+ import express from 'express';
5
+ import Router from 'express-promise-router';
6
+ import { TodoListService } from './services/TodoListService/types';
7
+
8
+ export async function createRouter({
9
+ httpAuth,
10
+ todoListService,
11
+ }: {
12
+ httpAuth: HttpAuthService;
13
+ todoListService: TodoListService;
14
+ }): Promise<express.Router> {
15
+ const router = Router();
16
+ router.use(express.json());
17
+
18
+ // TEMPLATE NOTE:
19
+ // Zod is a powerful library for data validation and recommended in particular
20
+ // for user-defined schemas. In this case we use it for input validation too.
21
+ //
22
+ // If you want to define a schema for your API we recommend using Backstage's
23
+ // OpenAPI tooling: https://backstage.io/docs/next/openapi/01-getting-started
24
+ const todoSchema = z.object({
25
+ title: z.string(),
26
+ entityRef: z.string().optional(),
27
+ });
28
+
29
+ router.post('/todos', async (req, res) => {
30
+ const parsed = todoSchema.safeParse(req.body);
31
+ if (!parsed.success) {
32
+ throw new InputError(parsed.error.toString());
33
+ }
34
+
35
+ const result = await todoListService.createTodo(parsed.data, {
36
+ credentials: await httpAuth.credentials(req, { allow: ['user'] }),
37
+ });
38
+
39
+ res.status(201).json(result);
40
+ });
41
+
42
+ router.get('/todos', async (_req, res) => {
43
+ res.json(await todoListService.listTodos());
44
+ });
45
+
46
+ router.get('/todos/:id', async (req, res) => {
47
+ res.json(await todoListService.getTodo({ id: req.params.id }));
48
+ });
49
+
50
+ return router;
51
+ }
@@ -0,0 +1,100 @@
1
+ import { AuthService, LoggerService } from '@backstage/backend-plugin-api';
2
+ import { NotFoundError } from '@backstage/errors';
3
+ import { catalogServiceRef } from '@backstage/plugin-catalog-node/alpha';
4
+ import crypto from 'node:crypto';
5
+ import { TodoItem, TodoListService } from './types';
6
+
7
+ // TEMPLATE NOTE:
8
+ // This is a simple in-memory todo list store. It is recommended to use a
9
+ // database to store data in a real application. See the database service
10
+ // documentation for more information on how to do this:
11
+ // https://backstage.io/docs/backend-system/core-services/database
12
+ export async function createTodoListService({
13
+ auth,
14
+ logger,
15
+ catalog,
16
+ }: {
17
+ auth: AuthService;
18
+ logger: LoggerService;
19
+ catalog: typeof catalogServiceRef.T;
20
+ }): Promise<TodoListService> {
21
+ logger.info('Initializing TodoListService');
22
+
23
+ const storedTodos = new Array<TodoItem>();
24
+
25
+ return {
26
+ async createTodo(input, options) {
27
+ let title = input.title;
28
+
29
+ // TEMPLATE NOTE:
30
+ // A common pattern for Backstage plugins is to pass an entity reference
31
+ // from the frontend to then fetch the entire entity from the catalog in the
32
+ // backend plugin.
33
+ if (input.entityRef) {
34
+ // TEMPLATE NOTE:
35
+ // Cross-plugin communication uses service-to-service authentication. The
36
+ // `AuthService` lets you generate a token that is valid for communication
37
+ // with the target plugin only. You must also provide credentials for the
38
+ // identity that you are making the request on behalf of.
39
+ //
40
+ // If you want to make a request using the plugin backend's own identity,
41
+ // you can access it via the `auth.getOwnServiceCredentials()` method.
42
+ // Beware that this bypasses any user permission checks.
43
+ const { token } = await auth.getPluginRequestToken({
44
+ onBehalfOf: options.credentials,
45
+ targetPluginId: 'catalog',
46
+ });
47
+ const entity = await catalog.getEntityByRef(input.entityRef, {
48
+ token,
49
+ });
50
+ if (!entity) {
51
+ throw new NotFoundError(
52
+ `No entity found for ref '${input.entityRef}'`,
53
+ );
54
+ }
55
+
56
+ // TEMPLATE NOTE:
57
+ // Here you could read any form of data from the entity. A common use case
58
+ // is to read the value of a custom annotation for your plugin. You can
59
+ // read more about how to add custom annotations here:
60
+ // https://backstage.io/docs/features/software-catalog/extending-the-model#adding-a-new-annotation
61
+ //
62
+ // In this example we just use the entity title to decorate the todo item.
63
+
64
+ const entityDisplay = entity.metadata.title ?? input.entityRef;
65
+ title = `[${entityDisplay}] ${input.title}`;
66
+ }
67
+
68
+ const id = crypto.randomUUID();
69
+ const createdBy = options.credentials.principal.userEntityRef;
70
+ const newTodo = {
71
+ title,
72
+ id,
73
+ createdBy,
74
+ createdAt: new Date().toISOString(),
75
+ };
76
+
77
+ storedTodos.push(newTodo);
78
+
79
+ // TEMPLATE NOTE:
80
+ // The second argument of the logger methods can be used to pass
81
+ // structured metadata. You can read more about the logger service here:
82
+ // https://backstage.io/docs/backend-system/core-services/logger
83
+ logger.info('Created new todo item', { id, title, createdBy });
84
+
85
+ return newTodo;
86
+ },
87
+
88
+ async listTodos() {
89
+ return { items: Array.from(storedTodos) };
90
+ },
91
+
92
+ async getTodo(request: { id: string }) {
93
+ const todo = storedTodos.find(item => item.id === request.id);
94
+ if (!todo) {
95
+ throw new NotFoundError(`No todo found with id '${request.id}'`);
96
+ }
97
+ return todo;
98
+ },
99
+ };
100
+ }
@@ -0,0 +1 @@
1
+ export { createTodoListService } from './createTodoListService';
@@ -0,0 +1,27 @@
1
+ import {
2
+ BackstageCredentials,
3
+ BackstageUserPrincipal,
4
+ } from '@backstage/backend-plugin-api';
5
+
6
+ export interface TodoItem {
7
+ title: string;
8
+ id: string;
9
+ createdBy: string;
10
+ createdAt: string;
11
+ }
12
+
13
+ export interface TodoListService {
14
+ createTodo(
15
+ input: {
16
+ title: string;
17
+ entityRef?: string;
18
+ },
19
+ options: {
20
+ credentials: BackstageCredentials<BackstageUserPrincipal>;
21
+ },
22
+ ): Promise<TodoItem>;
23
+
24
+ listTodos(): Promise<{ items: TodoItem[] }>;
25
+
26
+ getTodo(request: { id: string }): Promise<TodoItem>;
27
+ }
@@ -29,10 +29,12 @@
29
29
  "postpack": "backstage-cli package postpack"
30
30
  },
31
31
  "dependencies": {
32
+ "@backstage/backend-plugin-api": "{{versionQuery '@backstage/backend-plugin-api'}}",
32
33
  "@backstage/plugin-scaffolder-node": "{{versionQuery '@backstage/plugin-scaffolder-node'}}"
33
34
  },
34
35
  "devDependencies": {
35
- "@backstage/cli": "{{versionQuery '@backstage/cli'}}"
36
+ "@backstage/cli": "{{versionQuery '@backstage/cli'}}",
37
+ "@backstage/plugin-scaffolder-node-test-utils": "{{versionQuery '@backstage/plugin-scaffolder-node-test-utils'}}"
36
38
  },
37
39
  "files": [
38
40
  "dist"
@@ -0,0 +1,24 @@
1
+ import { createExampleAction } from './example';
2
+ import {createMockActionContext} from '@backstage/plugin-scaffolder-node-test-utils'
3
+
4
+ describe('createExampleAction', () => {
5
+ it('should call action', async () => {
6
+ const action = createExampleAction();
7
+
8
+ await expect(action.handler(createMockActionContext({
9
+ input: {
10
+ myParameter: 'test',
11
+ },
12
+ }))).resolves.toBeUndefined()
13
+ });
14
+
15
+ it('should fail when passing foo', async () => {
16
+ const action = createExampleAction();
17
+
18
+ await expect(action.handler(createMockActionContext({
19
+ input: {
20
+ myParameter: 'foo',
21
+ },
22
+ }))).rejects.toThrow("myParameter cannot be 'foo'")
23
+ });
24
+ });
@@ -9,14 +9,14 @@ import { createTemplateAction } from '@backstage/plugin-scaffolder-node';
9
9
  *
10
10
  * @public
11
11
  */
12
- export function createAcmeExampleAction() {
12
+ export function createExampleAction() {
13
13
  // For more information on how to define custom actions, see
14
14
  // https://backstage.io/docs/features/software-templates/writing-custom-actions
15
15
  return createTemplateAction<{
16
16
  myParameter: string;
17
17
  }>({
18
18
  id: 'acme:example',
19
- description: 'Runs Yeoman on an installed Yeoman generator',
19
+ description: 'Runs an example action',
20
20
  schema: {
21
21
  input: {
22
22
  type: 'object',
@@ -24,7 +24,7 @@ export function createAcmeExampleAction() {
24
24
  properties: {
25
25
  myParameter: {
26
26
  title: 'An example parameter',
27
- description: 'This is the schema for our example parameter',
27
+ description: "This is an example parameter, don't set it to foo",
28
28
  type: 'string',
29
29
  },
30
30
  },
@@ -35,6 +35,10 @@ export function createAcmeExampleAction() {
35
35
  `Running example template with parameters: ${ctx.input.myParameter}`,
36
36
  );
37
37
 
38
+ if (ctx.input.myParameter === 'foo') {
39
+ throw new Error(`myParameter cannot be 'foo'`);
40
+ }
41
+
38
42
  await new Promise(resolve => setTimeout(resolve, 1000));
39
43
  },
40
44
  });
@@ -5,4 +5,4 @@
5
5
  * @packageDocumentation
6
6
  */
7
7
 
8
- export * from './actions';
8
+ export { scaffolderModule as default } from './module';
@@ -1,12 +1,12 @@
1
1
  import { createBackendModule } from "@backstage/backend-plugin-api";
2
2
  import { scaffolderActionsExtensionPoint } from '@backstage/plugin-scaffolder-node/alpha';
3
- import { createAcmeExampleAction } from "./example";
3
+ import { createExampleAction } from "./actions/example";
4
4
 
5
5
  /**
6
6
  * A backend module that registers the action into the scaffolder
7
7
  */
8
8
  export const scaffolderModule = createBackendModule({
9
- moduleId: 'acme:example',
9
+ moduleId: 'example-action',
10
10
  pluginId: 'scaffolder',
11
11
  register({ registerInit }) {
12
12
  registerInit({
@@ -14,7 +14,7 @@ export const scaffolderModule = createBackendModule({
14
14
  scaffolderActions: scaffolderActionsExtensionPoint
15
15
  },
16
16
  async init({ scaffolderActions}) {
17
- scaffolderActions.addActions(createAcmeExampleAction());
17
+ scaffolderActions.addActions(createExampleAction());
18
18
  }
19
19
  });
20
20
  },
@@ -1,47 +0,0 @@
1
- 'use strict';
2
-
3
- var path = require('path');
4
- var cliCommon = require('@backstage/cli-common');
5
-
6
- class LinkedPackageResolvePlugin {
7
- constructor(targetModules, packages) {
8
- this.targetModules = targetModules;
9
- this.packages = packages;
10
- }
11
- apply(resolver) {
12
- resolver.hooks.resolve.tapAsync(
13
- "LinkedPackageResolvePlugin",
14
- (data, context, callback) => {
15
- const pkg = this.packages.find(
16
- (pkge) => data.path && cliCommon.isChildPath(pkge.dir, data.path)
17
- );
18
- if (!pkg) {
19
- callback();
20
- return;
21
- }
22
- const modulesLocation = path.resolve(
23
- this.targetModules,
24
- pkg.packageJson.name
25
- );
26
- const newContext = data.context?.issuer ? {
27
- ...data.context,
28
- issuer: data.context.issuer.replace(pkg.dir, modulesLocation)
29
- } : data.context;
30
- resolver.doResolve(
31
- resolver.hooks.resolve,
32
- {
33
- ...data,
34
- context: newContext,
35
- path: data.path && data.path.replace(pkg.dir, modulesLocation)
36
- },
37
- `resolve ${data.request} in ${modulesLocation}`,
38
- context,
39
- callback
40
- );
41
- }
42
- );
43
- }
44
- }
45
-
46
- exports.LinkedPackageResolvePlugin = LinkedPackageResolvePlugin;
47
- //# sourceMappingURL=LinkedPackageResolvePlugin.cjs.js.map
@@ -1,36 +0,0 @@
1
- 'use strict';
2
-
3
- var webpack = require('webpack');
4
- var config = require('./config.cjs.js');
5
- var paths = require('./paths.cjs.js');
6
-
7
- function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
8
-
9
- var webpack__default = /*#__PURE__*/_interopDefaultCompat(webpack);
10
-
11
- async function serveBackend(options) {
12
- const paths$1 = paths.resolveBundlingPaths(options);
13
- const config$1 = await config.createBackendConfig(paths$1, {
14
- ...options,
15
- isDev: true
16
- });
17
- process.env.NODE_ENV = "development";
18
- const compiler = webpack__default.default(config$1, (err) => {
19
- if (err) {
20
- console.error(err);
21
- } else console.log("Build succeeded");
22
- });
23
- const waitForExit = async () => {
24
- for (const signal of ["SIGINT", "SIGTERM"]) {
25
- process.on(signal, () => {
26
- compiler.close(() => process.exit());
27
- });
28
- }
29
- return new Promise(() => {
30
- });
31
- };
32
- return waitForExit;
33
- }
34
-
35
- exports.serveBackend = serveBackend;
36
- //# sourceMappingURL=backend.cjs.js.map
@@ -1,9 +0,0 @@
1
- import { createBackend } from '@backstage/backend-defaults';
2
-
3
- const backend = createBackend();
4
-
5
- backend.add(import('@backstage/plugin-auth-backend'));
6
- backend.add(import('@backstage/plugin-auth-backend-module-guest-provider'));
7
- backend.add(import('../src'));
8
-
9
- backend.start();
@@ -1,30 +0,0 @@
1
- import { mockServices } from '@backstage/backend-test-utils';
2
- import express from 'express';
3
- import request from 'supertest';
4
-
5
- import { createRouter } from './router';
6
-
7
- describe('createRouter', () => {
8
- let app: express.Express;
9
-
10
- beforeAll(async () => {
11
- const router = await createRouter({
12
- logger: mockServices.logger.mock(),
13
- config: mockServices.rootConfig(),
14
- });
15
- app = express().use(router);
16
- });
17
-
18
- beforeEach(() => {
19
- jest.resetAllMocks();
20
- });
21
-
22
- describe('GET /health', () => {
23
- it('returns ok', async () => {
24
- const response = await request(app).get('/health');
25
-
26
- expect(response.status).toEqual(200);
27
- expect(response.body).toEqual({ status: 'ok' });
28
- });
29
- });
30
- });