From 589860ec27f7fbe2cb96e5266737850a6c2c5ead Mon Sep 17 00:00:00 2001 From: Alper Altay Date: Mon, 24 Jun 2024 15:26:53 +0200 Subject: [PATCH] feat: add plugin to backend index.ts Signed-off-by: Alper Altay --- .../lib/new/factories/backendPlugin.test.ts | 88 ++++++++++++++++++- .../src/lib/new/factories/backendPlugin.ts | 34 +++++++ 2 files changed, 119 insertions(+), 3 deletions(-) diff --git a/packages/cli/src/lib/new/factories/backendPlugin.test.ts b/packages/cli/src/lib/new/factories/backendPlugin.test.ts index c5930592a3..c6196d8690 100644 --- a/packages/cli/src/lib/new/factories/backendPlugin.test.ts +++ b/packages/cli/src/lib/new/factories/backendPlugin.test.ts @@ -26,13 +26,19 @@ import { import { backendPlugin } from './backendPlugin'; import { createMockDirectory } from '@backstage/backend-test-utils'; +const backendIndexTsContent = ` +import { createBackend } from '@backstage/backend-defaults'; + +const backend = createBackend(); + +backend.start(); +`; + describe('backendPlugin factory', () => { const mockDir = createMockDirectory(); beforeEach(() => { - mockPaths({ - targetRoot: mockDir.path, - }); + mockPaths({ targetRoot: mockDir.path }); }); afterEach(() => { @@ -44,6 +50,9 @@ describe('backendPlugin factory', () => { packages: { backend: { 'package.json': JSON.stringify({}), + src: { + 'index.ts': backendIndexTsContent, + }, }, }, plugins: {}, @@ -89,6 +98,7 @@ describe('backendPlugin factory', () => { 'Installing:', `moving plugins${sep}test-backend`, 'backend adding dependency', + 'backend adding import and plugin', ]); await expect( @@ -99,6 +109,78 @@ describe('backendPlugin factory', () => { }, }); + await expect( + fs.readFile(mockDir.resolve('packages/backend/src/index.ts'), 'utf8'), + ).resolves.toBe(` +import { createBackend } from '@backstage/backend-defaults'; + +const backend = createBackend(); + +backend.add(import("backstage-plugin-test-backend")); +backend.start(); +`); + + expect(Task.forCommand).toHaveBeenCalledTimes(2); + expect(Task.forCommand).toHaveBeenCalledWith('yarn install', { + cwd: mockDir.resolve('plugins/test-backend'), + optional: true, + }); + expect(Task.forCommand).toHaveBeenCalledWith('yarn lint --fix', { + cwd: mockDir.resolve('plugins/test-backend'), + optional: true, + }); + }); + + it('should create a backend plugin with more options and codeowners', async () => { + mockDir.setContent({ + CODEOWNERS: '', + packages: { + backend: { + 'package.json': JSON.stringify({}), + src: { + 'index.ts': backendIndexTsContent, + }, + }, + }, + plugins: {}, + }); + + const options = await FactoryRegistry.populateOptions(backendPlugin, { + id: 'test', + owner: '@test-user', + }); + + const [, mockStream] = createMockOutputStream(); + jest.spyOn(process, 'stderr', 'get').mockReturnValue(mockStream); + jest.spyOn(Task, 'forCommand').mockResolvedValue(); + + await backendPlugin.create(options, { + scope: 'internal', + private: true, + isMonoRepo: true, + defaultVersion: '1.0.0', + markAsModified: () => {}, + createTemporaryDirectory: () => fs.mkdtemp('test'), + }); + + await expect( + fs.readJson(mockDir.resolve('packages/backend/package.json')), + ).resolves.toEqual({ + dependencies: { + '@internal/backstage-plugin-test-backend': '^1.0.0', + }, + }); + + await expect( + fs.readFile(mockDir.resolve('packages/backend/src/index.ts'), 'utf8'), + ).resolves.toBe(` +import { createBackend } from '@backstage/backend-defaults'; + +const backend = createBackend(); + +backend.add(import("@internal/backstage-plugin-test-backend")); +backend.start();`); + expect(Task.forCommand).toHaveBeenCalledTimes(2); expect(Task.forCommand).toHaveBeenCalledWith('yarn install', { cwd: mockDir.resolve('plugins/test-backend'), diff --git a/packages/cli/src/lib/new/factories/backendPlugin.ts b/packages/cli/src/lib/new/factories/backendPlugin.ts index 09ea98fbe7..06bc6bd366 100644 --- a/packages/cli/src/lib/new/factories/backendPlugin.ts +++ b/packages/cli/src/lib/new/factories/backendPlugin.ts @@ -78,6 +78,40 @@ export const backendPlugin = createFactory({ }, ); }); + + await Task.forItem('backend', 'adding import and plugin', async () => { + const backendFilePath = paths.resolveTargetRoot( + 'packages/backend/src/index.ts', + ); + if (!(await fs.pathExists(backendFilePath))) { + return; + } + const content = await fs.readFile(backendFilePath, 'utf8'); + const revLines = content.split('\n').reverse(); + + const lastImportIndex = revLines.findIndex(line => + line.match(/ from ("|').*("|')/), + ); + const lastBackendAddIndex = revLines.findIndex(line => + line.match(/backend.add/), + ); + + const backendAddLine = `backend.add(import("${name}"));`; + + if (lastImportIndex !== -1 && lastBackendAddIndex !== -1) { + if (!content.includes(backendAddLine)) { + const [indentation] = + revLines[lastBackendAddIndex + 1].match(/^\s*/) ?? []; + revLines.splice( + lastBackendAddIndex + 1, + 0, + indentation + backendAddLine, + ); + } + const newContent = revLines.reverse().join('\n'); + await fs.writeFile(backendFilePath, newContent, 'utf8'); + } + }); } if (options.owner) {