Skip to content

Commit

Permalink
feat(marketplace): refaactore and update ui
Browse files Browse the repository at this point in the history
Signed-off-by: Christoph Jerolimov <[email protected]>
  • Loading branch information
christoph-jerolimov committed Feb 11, 2025
1 parent d1a07d7 commit ec9f85b
Show file tree
Hide file tree
Showing 78 changed files with 3,535 additions and 448 deletions.
4 changes: 2 additions & 2 deletions workspaces/marketplace/app-config.dynamic.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ catalog:
rules:
- allow: [Plugin]
- type: url
target: https://github.com/redhat-developer/rhdh-plugins/blob/main/workspaces/marketplace/examples/all-pluginlists.yaml
target: https://github.com/redhat-developer/rhdh-plugins/blob/main/workspaces/marketplace/examples/all-collections.yaml
rules:
- allow: [PluginList]
- allow: [PluginCollection]

dynamicPlugins:
frontend:
Expand Down
6 changes: 3 additions & 3 deletions workspaces/marketplace/app-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ catalog:
API,
Resource,
Plugin,
PluginList,
PluginCollection,
Package,
Location,
]
Expand All @@ -98,9 +98,9 @@ catalog:
rules:
- allow: [Plugin]
- type: file
target: ../../examples/all-pluginlists.yaml
target: ../../examples/all-collections.yaml
rules:
- allow: [PluginList]
- allow: [PluginCollection]
- type: file
target: ../../examples/all-packages.yaml
rules:
Expand Down
8 changes: 8 additions & 0 deletions workspaces/marketplace/examples/all-collections.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
apiVersion: backstage.io/v1alpha1
kind: Location
metadata:
name: all-collections
description: A collection of marketplace plugin collections
spec:
targets:
- ./collections/featured.yaml
8 changes: 0 additions & 8 deletions workspaces/marketplace/examples/all-pluginlists.yaml

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
apiVersion: marketplace.backstage.io/v1alpha1
kind: PluginList
kind: PluginCollection
metadata:
name: featured-plugins
title: Featured Plugins
Expand Down
5 changes: 3 additions & 2 deletions workspaces/marketplace/packages/app/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ import { RequirePermission } from '@backstage/plugin-permission-react';
import { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common/alpha';

import { getAllThemes } from '@red-hat-developer-hub/backstage-plugin-theme';
import { MarketplacePage } from '@red-hat-developer-hub/backstage-plugin-marketplace';
import { MarketplaceTabbedPage as Marketplace } from '@red-hat-developer-hub/backstage-plugin-marketplace';

import { apis } from './apis';
import { entityPage } from './components/catalog/EntityPage';
Expand Down Expand Up @@ -115,7 +115,8 @@ const routes = (
</Route>
<Route path="/settings" element={<UserSettingsPage />} />
<Route path="/catalog-graph" element={<CatalogGraphPage />} />
<Route path="/marketplace" element={<MarketplacePage />} />

<Route path="/marketplace" element={<Marketplace />} />
</FlatRoutes>
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,6 @@ The YAML file is structured into the following sections:
This module provides different process used to ingest the `plugin` and `pluginList` entity into the software catalog.

- **MarketplacePluginProcessors** - Ingests `Plugin` entity into the catalog.
- **MarketplacePluginListProcessors** - Ingests `PluginList` entity into the catalog.
- **MarketplaceCollectionProcessors** - Ingests `PluginList` entity into the catalog.
- **LocalPluginInstallStatusProcessor** - Add and Update `entity.spec.installStatus` based on the packages installed in backstage workspaces.
- **DynamicPluginInstallStatusProcessor** - Add and Update `entity.spec.installStatus` based on the dynamic plugin installed in RHDH. This processor will work only when you have [scalprum-backend](https://github.com/janus-idp/backstage-showcase/tree/main/plugins/scalprum-backend) installed in your backstage instance.
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export class MarketplacePackageProcessor implements CatalogProcessor {
}

// @public (undocumented)
export class MarketplacePluginListProcessor implements CatalogProcessor {
export class MarketplaceCollectionProcessor implements CatalogProcessor {
// (undocumented)
getProcessorName(): string;
// (undocumented)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha';

import { MarketplacePluginProcessor } from './processors/MarketplacePluginProcessor';
import { MarketplacePluginListProcessor } from './processors/MarketplacePluginListProcessor';
import { MarketplaceCollectionProcessor } from './processors/MarketplaceCollectionProcessor';
import { DynamicPackageInstallStatusProcessor } from './processors/DynamicPackageInstallStatusProcessor';
import { LocalPackageInstallStatusProcessor } from './processors/LocalPackageInstallStatusProcessor';
import { MarketplacePackageProcessor } from './processors/MarketplacePackageProcessor';
Expand All @@ -43,7 +43,7 @@ export const catalogModuleMarketplace = createBackendModule({
async init({ logger, catalog, discovery, auth }) {
logger.info('Adding Marketplace processors to catalog...');
catalog.addProcessor(new MarketplacePluginProcessor());
catalog.addProcessor(new MarketplacePluginListProcessor());
catalog.addProcessor(new MarketplaceCollectionProcessor());
catalog.addProcessor(new LocalPackageInstallStatusProcessor());
catalog.addProcessor(new MarketplacePackageProcessor());
catalog.addProcessor(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,9 @@ export class LocalPackageInstallStatusProcessor implements CatalogProcessor {
}
}

async preProcessEntity(entity: MarketplacePackage): Promise<MarketplacePackage> {
async preProcessEntity(
entity: MarketplacePackage,
): Promise<MarketplacePackage> {
if (
entity.apiVersion === MARKETPLACE_API_VERSION &&
entity.kind === MarketplaceKind.Package
Expand All @@ -135,7 +137,11 @@ export class LocalPackageInstallStatusProcessor implements CatalogProcessor {
const packageName = entity.spec?.packageName;
// TODO const versions = entity.spec.version;

if (this.customPaths.some((cpath) => this.isPackageInstalled(packageName, cpath))) {
if (
this.customPaths.some(cpath =>
this.isPackageInstalled(packageName, cpath),
)
) {
installStatus = InstallStatus.Installed;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@
* limitations under the License.
*/

import { MarketplacePluginList } from '@red-hat-developer-hub/backstage-plugin-marketplace-common';
import { MarketplaceCollection } from '@red-hat-developer-hub/backstage-plugin-marketplace-common';

import { MarketplacePluginListProcessor } from './MarketplacePluginListProcessor';
import { MarketplaceCollectionProcessor } from './MarketplaceCollectionProcessor';

const pluginListEntity: MarketplacePluginList = {
const pluginListEntity: MarketplaceCollection = {
apiVersion: 'marketplace.backstage.io/v1alpha1',
metadata: {
name: 'testplugin',
Expand All @@ -32,15 +32,15 @@ const pluginListEntity: MarketplacePluginList = {
},
};

describe('MarketplacePluginListProcessor', () => {
describe('MarketplaceCollectionProcessor', () => {
it('should return processor name', () => {
const processor = new MarketplacePluginListProcessor();
const processor = new MarketplaceCollectionProcessor();

expect(processor.getProcessorName()).toBe('MarketplacePluginListProcessor');
expect(processor.getProcessorName()).toBe('MarketplaceCollectionProcessor');
});

it('should return pluginList', async () => {
const processor = new MarketplacePluginListProcessor();
const processor = new MarketplaceCollectionProcessor();

const emit = jest.fn();
await processor.postProcessEntity(
Expand All @@ -56,7 +56,7 @@ describe('MarketplacePluginListProcessor', () => {
});

it('should return validate the entity', async () => {
const processor = new MarketplacePluginListProcessor();
const processor = new MarketplaceCollectionProcessor();

expect(
await processor.validateEntityKind({ ...pluginListEntity, kind: 'test' }),
Expand All @@ -65,7 +65,7 @@ describe('MarketplacePluginListProcessor', () => {
});

it('should return pluginList entity with relation', async () => {
const processor = new MarketplacePluginListProcessor();
const processor = new MarketplaceCollectionProcessor();

const emit = jest.fn();
await processor.postProcessEntity(pluginListEntity, null as any, emit);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ const pluginListJsonSchema = {
/**
* @public
*/
export class MarketplacePluginListProcessor implements CatalogProcessor {
export class MarketplaceCollectionProcessor implements CatalogProcessor {
private readonly validators = [
entityKindSchemaValidator(pluginListJsonSchema),
];
Expand All @@ -147,7 +147,7 @@ export class MarketplacePluginListProcessor implements CatalogProcessor {

// Return processor name
getProcessorName(): string {
return 'MarketplacePluginListProcessor';
return 'MarketplaceCollectionProcessor';
}

async postProcessEntity(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ export class MarketplacePackageProcessor implements CatalogProcessor {
partOfPlugins.forEach((plugin: string) => {
const pluginRef = parseEntityRef({
name: plugin,
kind: MarketplaceKinds.plugin,
kind: MarketplaceKind.Plugin,
});
if (pluginRef) {
emit(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ export class MarketplacePluginProcessor implements CatalogProcessor {
const pkgName = typeof pkg === 'string' ? pkg : pkg?.name;
const packageRef = parseEntityRef({
name: pkgName,
kind: MarketplaceKinds.package,
kind: MarketplaceKind.Package,
});
if (packageRef) {
emit(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/

export * from './MarketplacePluginProcessor';
export * from './MarketplacePluginListProcessor';
export * from './MarketplaceCollectionProcessor';
export * from './DynamicPackageInstallStatusProcessor';
export * from './LocalPackageInstallStatusProcessor';
export * from './MarketplacePackageProcessor';
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { ExtendedHttpServer } from '@backstage/backend-defaults/dist/rootHttpRou
import {
encodeQueryParams,
MarketplacePlugin,
MarketplacePluginList,
MarketplaceCollection,
} from '@red-hat-developer-hub/backstage-plugin-marketplace-common';

const BASE_CONFIG = {
Expand Down Expand Up @@ -98,7 +98,7 @@ describe('createRouter', () => {
name,
kind = 'plugin',
}: {
mockData: MarketplacePlugin[] | MarketplacePluginList[] | {} | null;
mockData: MarketplacePlugin[] | MarketplaceCollection[] | {} | null;
name?: string;
kind?: string;
}): Promise<{ backendServer: ExtendedHttpServer }> => {
Expand Down
11 changes: 9 additions & 2 deletions workspaces/marketplace/plugins/marketplace-backend/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ import Router from 'express-promise-router';
import { HttpAuthService } from '@backstage/backend-plugin-api';
import { InputError, NotFoundError } from '@backstage/errors';
import {
decodeGetPackagesRequest,
decodeGetPluginsRequest,
decodeQueryParams,
EntityFacetSchema,
GetEntityFacetsRequest,
GetPluginsRequest,
MarketplaceApi,
MarketplaceKind,
} from '@red-hat-developer-hub/backstage-plugin-marketplace-common';
Expand All @@ -38,9 +38,16 @@ export async function createRouter({
const router = Router();
router.use(express.json());

router.get('/packages', async (req, res) => {
const query = req.url.split('?')[1] || '';
const request = decodeGetPackagesRequest(query);
const plugins = await marketplaceApi.getPackages(request);
res.json(plugins);
});

router.get('/plugins', async (req, res) => {
const query = req.url.split('?')[1] || '';
const request: GetPluginsRequest = decodeGetPluginsRequest(query);
const request = decodeGetPluginsRequest(query);
const plugins = await marketplaceApi.getPlugins(request);
res.json(plugins);
});
Expand Down
10 changes: 5 additions & 5 deletions workspaces/marketplace/plugins/marketplace-common/report.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,9 @@ export interface MarketplaceApi {
// (undocumented)
getPluginByName(name: string): Promise<MarketplacePlugin>;
// (undocumented)
getPluginListByName(name: string): Promise<MarketplacePluginList>;
getPluginListByName(name: string): Promise<MarketplaceCollection>;
// (undocumented)
getPluginLists(): Promise<MarketplacePluginList[]>;
getPluginLists(): Promise<MarketplaceCollection[]>;
// (undocumented)
getPlugins(request?: GetPluginsRequest): Promise<MarketplacePluginWithPageInfo>;
// (undocumented)
Expand All @@ -181,9 +181,9 @@ export class MarketplaceCatalogClient implements MarketplaceApi {
// (undocumented)
getPluginByName(name: string): Promise<MarketplacePlugin>;
// (undocumented)
getPluginListByName(name: string): Promise<MarketplacePluginList>;
getPluginListByName(name: string): Promise<MarketplaceCollection>;
// (undocumented)
getPluginLists(): Promise<MarketplacePluginList[]>;
getPluginLists(): Promise<MarketplaceCollection[]>;
// (undocumented)
getPlugins(request?: GetPluginsRequest): Promise<MarketplacePluginWithPageInfo>;
// (undocumented)
Expand Down Expand Up @@ -249,7 +249,7 @@ export interface MarketplacePlugin extends Entity {
}

// @public (undocumented)
export interface MarketplacePluginList extends Entity {
export interface MarketplaceCollection extends Entity {
// (undocumented)
spec?: {
plugins: string[];
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright 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 {
GetEntityFacetsRequest,
GetEntityFacetsResponse,
GetPackagesRequest,
GetPluginsRequest,
MarketplacePackage,
MarketplacePlugin,
MarketplaceCollection,
MarketplacePluginWithPageInfo,
} from '../types';

/**
* @public
*/
export interface PagedResponse<T> {
items: T[];
// TODO remove optionmal
totalItems?: number;
pageInfo?: {
nextCursor?: string;
prevCursor?: string;
};
}

/**
* @public
*/
export interface MarketplaceApi {
getPackages(
request?: GetPackagesRequest,
): Promise<PagedResponse<MarketplacePackage>>;
getPackagesFacets(): Promise<GetEntityFacetsResponse>;
getPackageByName(name: string): Promise<MarketplacePackage>;

getPlugins(
request?: GetPluginsRequest,
): Promise<MarketplacePluginWithPageInfo>;

getPluginByName(name: string): Promise<MarketplacePlugin>;

getPluginLists(): Promise<MarketplaceCollection[]>;
getPluginListByName(name: string): Promise<MarketplaceCollection>;
getPluginsByPluginListName(name: string): Promise<MarketplacePlugin[]>;

// TODO: fix types
getEntityFacets(
request: GetEntityFacetsRequest,
): Promise<GetEntityFacetsResponse>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ const options = {
getOwnServiceCredentials: jest
.fn()
.mockResolvedValue('mockedServiceCredentials'),
getPluginRequestToken: jest.fn().mockResolvedValue('mockedToken'),
getPluginRequestToken: jest
.fn()
.mockResolvedValue({ token: 'mockedToken' }),
} as any,
};

Expand Down
Loading

0 comments on commit ec9f85b

Please sign in to comment.