From e477ec4df2c016dde6361ffed0d024b986e4bff1 Mon Sep 17 00:00:00 2001 From: blbose Date: Tue, 14 Nov 2023 21:33:08 +0530 Subject: [PATCH 1/6] feat: codescene plugin at entity level Signed-off-by: blbose --- .changeset/beige-books-kiss.md | 5 + plugins/codescene/README.md | 31 ++++ plugins/codescene/package.json | 4 + .../CodeSceneEntityKPICard.test.tsx | 135 ++++++++++++++ .../CodeSceneEntityKPICard.tsx | 80 +++++++++ .../CodeSceneEntityKPICard/index.ts | 16 ++ .../CodeSceneEntityPage.test.tsx | 135 ++++++++++++++ .../CodeSceneEntityPage.tsx | 167 ++++++++++++++++++ .../components/CodeSceneEntityPage/index.ts | 16 ++ plugins/codescene/src/index.ts | 8 +- plugins/codescene/src/plugin.ts | 22 +++ plugins/codescene/src/utils/commonUtil.ts | 29 +++ yarn.lock | 2 + 13 files changed, 649 insertions(+), 1 deletion(-) create mode 100644 .changeset/beige-books-kiss.md create mode 100644 plugins/codescene/src/components/CodeSceneEntityKPICard/CodeSceneEntityKPICard.test.tsx create mode 100644 plugins/codescene/src/components/CodeSceneEntityKPICard/CodeSceneEntityKPICard.tsx create mode 100644 plugins/codescene/src/components/CodeSceneEntityKPICard/index.ts create mode 100644 plugins/codescene/src/components/CodeSceneEntityPage/CodeSceneEntityPage.test.tsx create mode 100644 plugins/codescene/src/components/CodeSceneEntityPage/CodeSceneEntityPage.tsx create mode 100644 plugins/codescene/src/components/CodeSceneEntityPage/index.ts create mode 100644 plugins/codescene/src/utils/commonUtil.ts diff --git a/.changeset/beige-books-kiss.md b/.changeset/beige-books-kiss.md new file mode 100644 index 0000000000..7c465874ea --- /dev/null +++ b/.changeset/beige-books-kiss.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-codescene': patch +--- + +Extending code scene plugin in Entity page. diff --git a/plugins/codescene/README.md b/plugins/codescene/README.md index 1a713c1589..5f0df2c5c7 100644 --- a/plugins/codescene/README.md +++ b/plugins/codescene/README.md @@ -60,3 +60,34 @@ proxy: codescene: baseUrl: https://codescene.my-company.net # replace with your own URL ``` + +5. Adding the codescene plugin to Entity page: + +```yaml +# Add `codescene` annotations to the `catalog-info.yaml` of an entity. +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage + annotations: + codescene.io/project-id: +``` + +```tsx +// In packages/app/src/components/catalog/EntityPage.tsx + +import { + CodeSceneEntityPage, + isCodeSceneAvailable, +} from '@backstage/plugin-codescene'; + +/* other EntityLayout.Route items... */ + + + +; +``` diff --git a/plugins/codescene/package.json b/plugins/codescene/package.json index cf18ebdaf5..005133af23 100644 --- a/plugins/codescene/package.json +++ b/plugins/codescene/package.json @@ -29,13 +29,17 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { + "@backstage/catalog-model": "workspace:^", "@backstage/config": "workspace:^", "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", "@backstage/errors": "workspace:^", + "@backstage/plugin-catalog-react": "workspace:^", + "@backstage/theme": "workspace:^", "@material-ui/core": "^4.12.2", "@material-ui/lab": "4.0.0-alpha.61", "@types/react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "luxon": "^3.4.4", "rc-progress": "3.5.1", "react-use": "^17.2.4" }, diff --git a/plugins/codescene/src/components/CodeSceneEntityKPICard/CodeSceneEntityKPICard.test.tsx b/plugins/codescene/src/components/CodeSceneEntityKPICard/CodeSceneEntityKPICard.test.tsx new file mode 100644 index 0000000000..f433f33ce5 --- /dev/null +++ b/plugins/codescene/src/components/CodeSceneEntityKPICard/CodeSceneEntityKPICard.test.tsx @@ -0,0 +1,135 @@ +/* + * Copyright 2023 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 React from 'react'; +import { CodeSceneEntityKPICard } from './CodeSceneEntityKPICard'; +import { rest } from 'msw'; +import { setupServer } from 'msw/node'; +import { + setupRequestMockHandlers, + renderInTestApp, + TestApiRegistry, +} from '@backstage/test-utils'; +import { CodeSceneApi, codesceneApiRef } from '../../api/api'; +import { ApiProvider } from '@backstage/core-app-api'; +import { Analysis } from '../../api/types'; +import { ConfigReader } from '@backstage/config'; +import { configApiRef } from '@backstage/core-plugin-api'; +import { EntityProvider } from '@backstage/plugin-catalog-react'; + +const entity = { + metadata: { + namespace: 'default', + annotations: { + 'codescene.io/project-id': '12345', + }, + name: 'codescene-test-project', + title: 'codescene-test-project', + description: 'A demo codescene-test repo', + links: [ + { + url: 'https://some-demo.com', + title: 'Demo', + icon: 'dashboard', + }, + ], + }, + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + spec: { + type: 'website', + owner: 'swcoe', + lifecycle: 'experimental', + }, + relations: [ + { + type: 'ownedBy', + targetRef: 'group:default/swcoe', + target: { + kind: 'group', + namespace: 'default', + name: 'swcoe', + }, + }, + ], +}; + +describe('CodeSceneEntityKPICard', () => { + const server = setupServer(); + // Enable same handlers for network requests + setupRequestMockHandlers(server); + let apis: TestApiRegistry; + + // setup mock response + beforeEach(() => { + server.use( + rest.get('/*', (_, res, ctx) => res(ctx.status(200), ctx.json({}))), + ); + + const config = new ConfigReader({ + codescene: { + baseUrl: 'www.fake-url.com', + }, + }); + const analysis: Analysis = { + id: 1, + name: 'codescene-test-project', + project_id: 12345, + readable_analysis_time: '2022-03-22', + summary: { + unique_issue_ids: 0, + issues_filtered_as_outliers: 0, + entities: 0, + commits_with_issue_ids: 0, + authors_count: 0, + active_authors_count: 0, + issues_with_cycle_time: 0, + commits: 0, + issue_ids_matched_to_issues: 0, + issues_classed_as_defects: 0, + issues_with_cost: 0, + }, + file_summary: [], + high_level_metrics: { + current_score: 0, + month_score: 0, + year_score: 0, + active_developers: 0, + lines_of_code: 0, + system_mastery: 0, + }, + }; + apis = TestApiRegistry.from( + [ + codesceneApiRef, + { + fetchLatestAnalysis: jest.fn(() => analysis), + } as unknown as CodeSceneApi, + ], + [configApiRef, config], + ); + }); + + it('should render', async () => { + const rendered = await renderInTestApp( + + + + + , + ); + expect(rendered.getByText(/Mar 22, 2022/i)).toBeInTheDocument(); + }); +}); diff --git a/plugins/codescene/src/components/CodeSceneEntityKPICard/CodeSceneEntityKPICard.tsx b/plugins/codescene/src/components/CodeSceneEntityKPICard/CodeSceneEntityKPICard.tsx new file mode 100644 index 0000000000..0f348eaf3f --- /dev/null +++ b/plugins/codescene/src/components/CodeSceneEntityKPICard/CodeSceneEntityKPICard.tsx @@ -0,0 +1,80 @@ +/* + * Copyright 2023 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 { + Content, + EmptyState, + Progress, + ContentHeader, +} from '@backstage/core-components'; +import { configApiRef, useApi } from '@backstage/core-plugin-api'; +import Alert from '@material-ui/lab/Alert'; +import React from 'react'; +import { useEntity } from '@backstage/plugin-catalog-react'; +import useAsync from 'react-use/lib/useAsync'; +import { codesceneApiRef } from '../../api/api'; +import { Analysis } from '../../api/types'; +import { CodeHealthKpisCard } from '../CodeHealthKpisCard/CodeHealthKpisCard'; +import { + getProjectAnnotation, + CODESCENE_PROJECT_ANNOTATION, + isCodeSceneAvailable, +} from '../../utils/commonUtil'; +import { DateTime } from 'luxon'; +import { MissingAnnotationEmptyState } from '@backstage/plugin-catalog-react'; + +export const CodeSceneEntityKPICard = () => { + const { entity } = useEntity(); + const { projectId } = getProjectAnnotation(entity); + const codesceneApi = useApi(codesceneApiRef); + const config = useApi(configApiRef); + const codesceneHost = config.getString('codescene.baseUrl'); + + const { + value: analysis, + loading, + error, + } = useAsync(async (): Promise => { + return await codesceneApi.fetchLatestAnalysis(projectId); + }, []); + + if (loading) { + return ; + } else if (error) { + return {error.message}; + } else if (!analysis) { + return ( + + ); + } + + return isCodeSceneAvailable(entity) ? ( + + + Last analyzed on{' '} + {DateTime.fromISO(analysis.readable_analysis_time).toLocaleString( + DateTime.DATETIME_MED, + )} + + + + ) : ( + + ); +}; diff --git a/plugins/codescene/src/components/CodeSceneEntityKPICard/index.ts b/plugins/codescene/src/components/CodeSceneEntityKPICard/index.ts new file mode 100644 index 0000000000..934705e321 --- /dev/null +++ b/plugins/codescene/src/components/CodeSceneEntityKPICard/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export { CodeSceneEntityKPICard } from './CodeSceneEntityKPICard'; diff --git a/plugins/codescene/src/components/CodeSceneEntityPage/CodeSceneEntityPage.test.tsx b/plugins/codescene/src/components/CodeSceneEntityPage/CodeSceneEntityPage.test.tsx new file mode 100644 index 0000000000..96fd16aa62 --- /dev/null +++ b/plugins/codescene/src/components/CodeSceneEntityPage/CodeSceneEntityPage.test.tsx @@ -0,0 +1,135 @@ +/* + * Copyright 2023 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 React from 'react'; +import { CodeSceneEntityPage } from './CodeSceneEntityPage'; +import { rest } from 'msw'; +import { setupServer } from 'msw/node'; +import { + setupRequestMockHandlers, + renderInTestApp, + TestApiRegistry, +} from '@backstage/test-utils'; +import { CodeSceneApi, codesceneApiRef } from '../../api/api'; +import { ApiProvider } from '@backstage/core-app-api'; +import { Analysis } from '../../api/types'; +import { ConfigReader } from '@backstage/config'; +import { configApiRef } from '@backstage/core-plugin-api'; +import { EntityProvider } from '@backstage/plugin-catalog-react'; + +const entity = { + metadata: { + namespace: 'default', + annotations: { + 'codescene.io/project-id': '12345', + }, + name: 'codescene-test-project', + title: 'codescene-test-project', + description: 'A demo codescene-test repo', + links: [ + { + url: 'https://some-demo.com', + title: 'Demo', + icon: 'dashboard', + }, + ], + }, + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + spec: { + type: 'website', + owner: 'swcoe', + lifecycle: 'experimental', + }, + relations: [ + { + type: 'ownedBy', + targetRef: 'group:default/swcoe', + target: { + kind: 'group', + namespace: 'default', + name: 'swcoe', + }, + }, + ], +}; + +describe('CodeSceneEntityPage', () => { + const server = setupServer(); + // Enable sane handlers for network requests + setupRequestMockHandlers(server); + let apis: TestApiRegistry; + + // setup mock response + beforeEach(() => { + server.use( + rest.get('/*', (_, res, ctx) => res(ctx.status(200), ctx.json({}))), + ); + + const config = new ConfigReader({ + codescene: { + baseUrl: 'www.fake-url.com', + }, + }); + const analysis: Analysis = { + id: 1, + name: 'codescene-test-project', + project_id: 12345, + readable_analysis_time: '2022-03-22', + summary: { + unique_issue_ids: 0, + issues_filtered_as_outliers: 0, + entities: 0, + commits_with_issue_ids: 0, + authors_count: 0, + active_authors_count: 0, + issues_with_cycle_time: 0, + commits: 0, + issue_ids_matched_to_issues: 0, + issues_classed_as_defects: 0, + issues_with_cost: 0, + }, + file_summary: [], + high_level_metrics: { + current_score: 0, + month_score: 0, + year_score: 0, + active_developers: 0, + lines_of_code: 0, + system_mastery: 0, + }, + }; + apis = TestApiRegistry.from( + [ + codesceneApiRef, + { + fetchLatestAnalysis: jest.fn(() => analysis), + } as unknown as CodeSceneApi, + ], + [configApiRef, config], + ); + }); + + it('should render', async () => { + const rendered = await renderInTestApp( + + + + + , + ); + expect(rendered.getByText(/codescene-test-project/i)).toBeInTheDocument(); + }); +}); diff --git a/plugins/codescene/src/components/CodeSceneEntityPage/CodeSceneEntityPage.tsx b/plugins/codescene/src/components/CodeSceneEntityPage/CodeSceneEntityPage.tsx new file mode 100644 index 0000000000..19d2636fe9 --- /dev/null +++ b/plugins/codescene/src/components/CodeSceneEntityPage/CodeSceneEntityPage.tsx @@ -0,0 +1,167 @@ +/* + * Copyright 2023 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 { + Content, + EmptyState, + GaugeCard, + Header, + InfoCard, + Page, + Progress, + SupportButton, + Table, + TableColumn, +} from '@backstage/core-components'; +import { configApiRef, useApi } from '@backstage/core-plugin-api'; +import { Grid, Typography } from '@material-ui/core'; +import Alert from '@material-ui/lab/Alert'; +import React from 'react'; +import { useEntity } from '@backstage/plugin-catalog-react'; +import useAsync from 'react-use/lib/useAsync'; +import { codesceneApiRef } from '../../api/api'; +import { Analysis } from '../../api/types'; +import { CodeHealthKpisCard } from '../CodeHealthKpisCard/CodeHealthKpisCard'; +import { MissingAnnotationEmptyState } from '@backstage/plugin-catalog-react'; +import { + getProjectAnnotation, + CODESCENE_PROJECT_ANNOTATION, + isCodeSceneAvailable, +} from '../../utils/commonUtil'; + +export const CodeSceneEntityPage = () => { + const { entity } = useEntity(); + const { projectId } = getProjectAnnotation(entity); + const codesceneApi = useApi(codesceneApiRef); + const config = useApi(configApiRef); + const { + value: analysis, + loading, + error, + } = useAsync(async (): Promise => { + return await codesceneApi.fetchLatestAnalysis(projectId); + }, []); + + if (loading) { + return ; + } else if (error) { + return {error.message}; + } else if (!analysis) { + return ( + + ); + } + + const columns: TableColumn[] = [ + { + title: 'Language', + field: 'language', + highlight: true, + }, + { + title: 'Files', + field: 'number_of_files', + type: 'numeric', + }, + { + title: 'Code', + field: 'code', + type: 'numeric', + }, + { + title: 'Comment', + field: 'comment', + type: 'numeric', + }, + ]; + + const fileSummaryTable = ( + b.code - a.code)} + columns={columns} + title="File Summary" + /> + ); + + const codesceneHost = config.getString('codescene.baseUrl'); + const analysisPath = `${codesceneHost}/${projectId}/analyses/${analysis.id}`; + const analysisLink = { title: 'Check the analysis', link: analysisPath }; + + const analysisBody = ( + <> + + Active authors: {analysis.summary.active_authors_count} + + + Total authors: {analysis.summary.authors_count} + + + Commits: {analysis.summary.commits} + + + ); + + return isCodeSceneAvailable(entity) ? ( + +
+ + See hidden risks and social patterns in your code. Prioritize and + reduce technical debt. + +
+ + + + + + + + + + + + + + + {analysisBody} + + + + + {fileSummaryTable} + + +
+ ) : ( + + ); +}; diff --git a/plugins/codescene/src/components/CodeSceneEntityPage/index.ts b/plugins/codescene/src/components/CodeSceneEntityPage/index.ts new file mode 100644 index 0000000000..3909fb4861 --- /dev/null +++ b/plugins/codescene/src/components/CodeSceneEntityPage/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export { CodeSceneEntityPage } from './CodeSceneEntityPage'; diff --git a/plugins/codescene/src/index.ts b/plugins/codescene/src/index.ts index 301b4377a7..414af61d04 100644 --- a/plugins/codescene/src/index.ts +++ b/plugins/codescene/src/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Backstage Authors + * Copyright 2023 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. @@ -17,5 +17,11 @@ export { codescenePlugin, CodeScenePage, CodeSceneProjectDetailsPage, + CodeSceneEntityPage, + CodeSceneEntityKPICard, } from './plugin'; export { CodeSceneIcon } from './CodeSceneIcon'; +export { + isCodeSceneAvailable, + CODESCENE_PROJECT_ANNOTATION, +} from './utils/commonUtil'; diff --git a/plugins/codescene/src/plugin.ts b/plugins/codescene/src/plugin.ts index b4e297345d..5c1a8e2e14 100644 --- a/plugins/codescene/src/plugin.ts +++ b/plugins/codescene/src/plugin.ts @@ -67,3 +67,25 @@ export const CodeSceneProjectDetailsPage = codescenePlugin.provide( mountPoint: projectDetailsRouteRef, }), ); + +export const CodeSceneEntityKPICard = codescenePlugin.provide( + createRoutableExtension({ + name: 'CodeSceneEntityKPICard', + component: () => + import('./components/CodeSceneEntityKPICard').then( + m => m.CodeSceneEntityKPICard, + ), + mountPoint: rootRouteRef, + }), +); + +export const CodeSceneEntityPage = codescenePlugin.provide( + createRoutableExtension({ + name: 'CodeSceneEntityPage', + component: () => + import('./components/CodeSceneEntityPage').then( + m => m.CodeSceneEntityPage, + ), + mountPoint: rootRouteRef, + }), +); diff --git a/plugins/codescene/src/utils/commonUtil.ts b/plugins/codescene/src/utils/commonUtil.ts new file mode 100644 index 0000000000..830cc797c9 --- /dev/null +++ b/plugins/codescene/src/utils/commonUtil.ts @@ -0,0 +1,29 @@ +/* + * Copyright 2023 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 { Entity } from '@backstage/catalog-model'; + +export const CODESCENE_PROJECT_ANNOTATION = 'codescene.io/project-id'; + +export const getProjectAnnotation = (entity: Entity) => { + const annotation = + entity?.metadata.annotations?.[CODESCENE_PROJECT_ANNOTATION]; + const projectId = annotation?.split('/')[0]; + return { projectId: Number(projectId) }; +}; + +export const isCodeSceneAvailable = (entity: Entity) => + Boolean(getProjectAnnotation(entity).projectId); diff --git a/yarn.lock b/yarn.lock index 53c220af6d..7105733663 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6073,6 +6073,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-codescene@workspace:plugins/codescene" dependencies: + "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" "@backstage/core-app-api": "workspace:^" @@ -6080,6 +6081,7 @@ __metadata: "@backstage/core-plugin-api": "workspace:^" "@backstage/dev-utils": "workspace:^" "@backstage/errors": "workspace:^" + "@backstage/plugin-catalog-react": "workspace:^" "@backstage/test-utils": "workspace:^" "@material-ui/core": ^4.12.2 "@material-ui/lab": 4.0.0-alpha.61 From 99c08a8980a62565f9ef80c554241f2b585de10e Mon Sep 17 00:00:00 2001 From: blbose Date: Tue, 14 Nov 2023 22:06:27 +0530 Subject: [PATCH 2/6] fix: api-report exceptions Signed-off-by: blbose --- plugins/codescene/api-report.md | 13 +++++++++++++ plugins/codescene/src/plugin.ts | 6 ++++++ plugins/codescene/src/utils/commonUtil.ts | 9 +++++++++ 3 files changed, 28 insertions(+) diff --git a/plugins/codescene/api-report.md b/plugins/codescene/api-report.md index 99eb2b6256..37018ea14b 100644 --- a/plugins/codescene/api-report.md +++ b/plugins/codescene/api-report.md @@ -6,10 +6,20 @@ /// import { BackstagePlugin } from '@backstage/core-plugin-api'; +import { Entity } from '@backstage/catalog-model'; import { IconComponent } from '@backstage/core-plugin-api'; import { JSX as JSX_2 } from 'react'; import { RouteRef } from '@backstage/core-plugin-api'; +// @public (undocumented) +export const CODESCENE_PROJECT_ANNOTATION = 'codescene.io/project-id'; + +// @public (undocumented) +export const CodeSceneEntityKPICard: () => JSX_2.Element; + +// @public (undocumented) +export const CodeSceneEntityPage: () => JSX_2.Element; + // @public (undocumented) export const CodeSceneIcon: IconComponent; @@ -30,5 +40,8 @@ export const codescenePlugin: BackstagePlugin< // @public (undocumented) export const CodeSceneProjectDetailsPage: () => JSX_2.Element; +// @public (undocumented) +export const isCodeSceneAvailable: (entity: Entity) => boolean; + // (No @packageDocumentation comment for this package) ``` diff --git a/plugins/codescene/src/plugin.ts b/plugins/codescene/src/plugin.ts index 5c1a8e2e14..70cb3fb2a5 100644 --- a/plugins/codescene/src/plugin.ts +++ b/plugins/codescene/src/plugin.ts @@ -68,6 +68,9 @@ export const CodeSceneProjectDetailsPage = codescenePlugin.provide( }), ); +/** + * @public + */ export const CodeSceneEntityKPICard = codescenePlugin.provide( createRoutableExtension({ name: 'CodeSceneEntityKPICard', @@ -79,6 +82,9 @@ export const CodeSceneEntityKPICard = codescenePlugin.provide( }), ); +/** + * @public + */ export const CodeSceneEntityPage = codescenePlugin.provide( createRoutableExtension({ name: 'CodeSceneEntityPage', diff --git a/plugins/codescene/src/utils/commonUtil.ts b/plugins/codescene/src/utils/commonUtil.ts index 830cc797c9..435cb377e6 100644 --- a/plugins/codescene/src/utils/commonUtil.ts +++ b/plugins/codescene/src/utils/commonUtil.ts @@ -16,8 +16,14 @@ import { Entity } from '@backstage/catalog-model'; +/** + * @public + */ export const CODESCENE_PROJECT_ANNOTATION = 'codescene.io/project-id'; +/** + * @public + */ export const getProjectAnnotation = (entity: Entity) => { const annotation = entity?.metadata.annotations?.[CODESCENE_PROJECT_ANNOTATION]; @@ -25,5 +31,8 @@ export const getProjectAnnotation = (entity: Entity) => { return { projectId: Number(projectId) }; }; +/** + * @public + */ export const isCodeSceneAvailable = (entity: Entity) => Boolean(getProjectAnnotation(entity).projectId); From 349ca6d3b6def541313c8a5cbec8e443a5f66015 Mon Sep 17 00:00:00 2001 From: blbose Date: Thu, 23 Nov 2023 20:24:13 +0530 Subject: [PATCH 3/6] fix: review comments on codescene entity changes Signed-off-by: blbose --- plugins/codescene/README.md | 10 +- plugins/codescene/api-report.md | 4 +- .../CodeSceneEntityFileSummary.tsx | 66 +++++++ .../index.ts | 2 +- .../CodeSceneEntityKPICard.test.tsx | 135 -------------- .../CodeSceneEntityKPICard.tsx | 81 +++++++-- .../CodeSceneEntityPage.test.tsx | 135 -------------- .../CodeSceneEntityPage.tsx | 167 ------------------ .../CodeSceneProjectDetailsPage.tsx | 66 ++++--- plugins/codescene/src/hooks/useAnalyses.ts | 34 ++++ plugins/codescene/src/index.ts | 2 +- plugins/codescene/src/plugin.ts | 31 ++-- 12 files changed, 226 insertions(+), 507 deletions(-) create mode 100644 plugins/codescene/src/components/CodeSceneEntityFileSummary/CodeSceneEntityFileSummary.tsx rename plugins/codescene/src/components/{CodeSceneEntityPage => CodeSceneEntityFileSummary}/index.ts (88%) delete mode 100644 plugins/codescene/src/components/CodeSceneEntityKPICard/CodeSceneEntityKPICard.test.tsx delete mode 100644 plugins/codescene/src/components/CodeSceneEntityPage/CodeSceneEntityPage.test.tsx delete mode 100644 plugins/codescene/src/components/CodeSceneEntityPage/CodeSceneEntityPage.tsx create mode 100644 plugins/codescene/src/hooks/useAnalyses.ts diff --git a/plugins/codescene/README.md b/plugins/codescene/README.md index 5f0df2c5c7..8c336bf74f 100644 --- a/plugins/codescene/README.md +++ b/plugins/codescene/README.md @@ -78,6 +78,7 @@ metadata: import { CodeSceneEntityPage, + CodeSceneEntityFileSummary, isCodeSceneAvailable, } from '@backstage/plugin-codescene'; @@ -88,6 +89,13 @@ import { title="codescene" if={isCodeSceneAvailable} > - + + + + + + + + ; ``` diff --git a/plugins/codescene/api-report.md b/plugins/codescene/api-report.md index 37018ea14b..33b994ea6e 100644 --- a/plugins/codescene/api-report.md +++ b/plugins/codescene/api-report.md @@ -15,10 +15,10 @@ import { RouteRef } from '@backstage/core-plugin-api'; export const CODESCENE_PROJECT_ANNOTATION = 'codescene.io/project-id'; // @public (undocumented) -export const CodeSceneEntityKPICard: () => JSX_2.Element; +export const CodeSceneEntityFileSummary: () => JSX_2.Element; // @public (undocumented) -export const CodeSceneEntityPage: () => JSX_2.Element; +export const CodeSceneEntityKPICard: () => JSX_2.Element; // @public (undocumented) export const CodeSceneIcon: IconComponent; diff --git a/plugins/codescene/src/components/CodeSceneEntityFileSummary/CodeSceneEntityFileSummary.tsx b/plugins/codescene/src/components/CodeSceneEntityFileSummary/CodeSceneEntityFileSummary.tsx new file mode 100644 index 0000000000..db5cef8c44 --- /dev/null +++ b/plugins/codescene/src/components/CodeSceneEntityFileSummary/CodeSceneEntityFileSummary.tsx @@ -0,0 +1,66 @@ +/* + * Copyright 2022 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 { Content, EmptyState, InfoCard } from '@backstage/core-components'; +import { Grid } from '@material-ui/core'; +import Alert from '@material-ui/lab/Alert'; +import React from 'react'; +import { + useEntity, + MissingAnnotationEmptyState, +} from '@backstage/plugin-catalog-react'; +import { + getProjectAnnotation, + CODESCENE_PROJECT_ANNOTATION, + isCodeSceneAvailable, +} from '../../utils/commonUtil'; +import { useAnalyses } from '../../hooks/useAnalyses'; +import { useApp } from '@backstage/core-plugin-api'; +import { CodeSceneFileSummary } from '../CodeSceneProjectDetailsPage/CodeSceneProjectDetailsPage'; + +export const CodeSceneEntityFileSummary = () => { + const { entity } = useEntity(); + const { projectId } = getProjectAnnotation(entity); + const { Progress } = useApp().getComponents(); + const { analysis, loading, error } = useAnalyses(projectId); + + if (loading) { + return ; + } else if (error) { + return {error.message}; + } else if (!analysis) { + return ( + + ); + } + + return isCodeSceneAvailable(entity) ? ( + + + + + + + + + + ) : ( + + ); +}; diff --git a/plugins/codescene/src/components/CodeSceneEntityPage/index.ts b/plugins/codescene/src/components/CodeSceneEntityFileSummary/index.ts similarity index 88% rename from plugins/codescene/src/components/CodeSceneEntityPage/index.ts rename to plugins/codescene/src/components/CodeSceneEntityFileSummary/index.ts index 3909fb4861..7495fe26ef 100644 --- a/plugins/codescene/src/components/CodeSceneEntityPage/index.ts +++ b/plugins/codescene/src/components/CodeSceneEntityFileSummary/index.ts @@ -13,4 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { CodeSceneEntityPage } from './CodeSceneEntityPage'; +export { CodeSceneEntityFileSummary } from './CodeSceneEntityFileSummary'; diff --git a/plugins/codescene/src/components/CodeSceneEntityKPICard/CodeSceneEntityKPICard.test.tsx b/plugins/codescene/src/components/CodeSceneEntityKPICard/CodeSceneEntityKPICard.test.tsx deleted file mode 100644 index f433f33ce5..0000000000 --- a/plugins/codescene/src/components/CodeSceneEntityKPICard/CodeSceneEntityKPICard.test.tsx +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2023 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 React from 'react'; -import { CodeSceneEntityKPICard } from './CodeSceneEntityKPICard'; -import { rest } from 'msw'; -import { setupServer } from 'msw/node'; -import { - setupRequestMockHandlers, - renderInTestApp, - TestApiRegistry, -} from '@backstage/test-utils'; -import { CodeSceneApi, codesceneApiRef } from '../../api/api'; -import { ApiProvider } from '@backstage/core-app-api'; -import { Analysis } from '../../api/types'; -import { ConfigReader } from '@backstage/config'; -import { configApiRef } from '@backstage/core-plugin-api'; -import { EntityProvider } from '@backstage/plugin-catalog-react'; - -const entity = { - metadata: { - namespace: 'default', - annotations: { - 'codescene.io/project-id': '12345', - }, - name: 'codescene-test-project', - title: 'codescene-test-project', - description: 'A demo codescene-test repo', - links: [ - { - url: 'https://some-demo.com', - title: 'Demo', - icon: 'dashboard', - }, - ], - }, - apiVersion: 'backstage.io/v1alpha1', - kind: 'Component', - spec: { - type: 'website', - owner: 'swcoe', - lifecycle: 'experimental', - }, - relations: [ - { - type: 'ownedBy', - targetRef: 'group:default/swcoe', - target: { - kind: 'group', - namespace: 'default', - name: 'swcoe', - }, - }, - ], -}; - -describe('CodeSceneEntityKPICard', () => { - const server = setupServer(); - // Enable same handlers for network requests - setupRequestMockHandlers(server); - let apis: TestApiRegistry; - - // setup mock response - beforeEach(() => { - server.use( - rest.get('/*', (_, res, ctx) => res(ctx.status(200), ctx.json({}))), - ); - - const config = new ConfigReader({ - codescene: { - baseUrl: 'www.fake-url.com', - }, - }); - const analysis: Analysis = { - id: 1, - name: 'codescene-test-project', - project_id: 12345, - readable_analysis_time: '2022-03-22', - summary: { - unique_issue_ids: 0, - issues_filtered_as_outliers: 0, - entities: 0, - commits_with_issue_ids: 0, - authors_count: 0, - active_authors_count: 0, - issues_with_cycle_time: 0, - commits: 0, - issue_ids_matched_to_issues: 0, - issues_classed_as_defects: 0, - issues_with_cost: 0, - }, - file_summary: [], - high_level_metrics: { - current_score: 0, - month_score: 0, - year_score: 0, - active_developers: 0, - lines_of_code: 0, - system_mastery: 0, - }, - }; - apis = TestApiRegistry.from( - [ - codesceneApiRef, - { - fetchLatestAnalysis: jest.fn(() => analysis), - } as unknown as CodeSceneApi, - ], - [configApiRef, config], - ); - }); - - it('should render', async () => { - const rendered = await renderInTestApp( - - - - - , - ); - expect(rendered.getByText(/Mar 22, 2022/i)).toBeInTheDocument(); - }); -}); diff --git a/plugins/codescene/src/components/CodeSceneEntityKPICard/CodeSceneEntityKPICard.tsx b/plugins/codescene/src/components/CodeSceneEntityKPICard/CodeSceneEntityKPICard.tsx index 0f348eaf3f..1757ad19cf 100644 --- a/plugins/codescene/src/components/CodeSceneEntityKPICard/CodeSceneEntityKPICard.tsx +++ b/plugins/codescene/src/components/CodeSceneEntityKPICard/CodeSceneEntityKPICard.tsx @@ -13,13 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { - Content, - EmptyState, - Progress, - ContentHeader, -} from '@backstage/core-components'; -import { configApiRef, useApi } from '@backstage/core-plugin-api'; +import { EmptyState, GaugeCard, InfoCard } from '@backstage/core-components'; +import { configApiRef, useApi, useApp } from '@backstage/core-plugin-api'; import Alert from '@material-ui/lab/Alert'; import React from 'react'; import { useEntity } from '@backstage/plugin-catalog-react'; @@ -34,6 +29,7 @@ import { } from '../../utils/commonUtil'; import { DateTime } from 'luxon'; import { MissingAnnotationEmptyState } from '@backstage/plugin-catalog-react'; +import { Grid, Typography } from '@material-ui/core'; export const CodeSceneEntityKPICard = () => { const { entity } = useEntity(); @@ -41,6 +37,7 @@ export const CodeSceneEntityKPICard = () => { const codesceneApi = useApi(codesceneApiRef); const config = useApi(configApiRef); const codesceneHost = config.getString('codescene.baseUrl'); + const { Progress } = useApp().getComponents(); const { value: analysis, @@ -64,16 +61,68 @@ export const CodeSceneEntityKPICard = () => { ); } + const analysisPath = `${codesceneHost}/${projectId}/analyses/${analysis.id}`; + const analysisLink = { title: 'Check the analysis', link: analysisPath }; + + const analysisBody = ( + <> + + Active authors: {analysis.summary.active_authors_count} + + + Total authors: {analysis.summary.authors_count} + + + Commits: {analysis.summary.commits} + + + ); + return isCodeSceneAvailable(entity) ? ( - - - Last analyzed on{' '} - {DateTime.fromISO(analysis.readable_analysis_time).toLocaleString( - DateTime.DATETIME_MED, - )} - - - + <> + + + + + + + + + + + + + + + + + + + {analysisBody} + + + +
+ {`Last analyzed on ${DateTime.fromISO( + analysis.readable_analysis_time, + ).toLocaleString(DateTime.DATETIME_MED)}`} +
+ ) : ( ); diff --git a/plugins/codescene/src/components/CodeSceneEntityPage/CodeSceneEntityPage.test.tsx b/plugins/codescene/src/components/CodeSceneEntityPage/CodeSceneEntityPage.test.tsx deleted file mode 100644 index 96fd16aa62..0000000000 --- a/plugins/codescene/src/components/CodeSceneEntityPage/CodeSceneEntityPage.test.tsx +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2023 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 React from 'react'; -import { CodeSceneEntityPage } from './CodeSceneEntityPage'; -import { rest } from 'msw'; -import { setupServer } from 'msw/node'; -import { - setupRequestMockHandlers, - renderInTestApp, - TestApiRegistry, -} from '@backstage/test-utils'; -import { CodeSceneApi, codesceneApiRef } from '../../api/api'; -import { ApiProvider } from '@backstage/core-app-api'; -import { Analysis } from '../../api/types'; -import { ConfigReader } from '@backstage/config'; -import { configApiRef } from '@backstage/core-plugin-api'; -import { EntityProvider } from '@backstage/plugin-catalog-react'; - -const entity = { - metadata: { - namespace: 'default', - annotations: { - 'codescene.io/project-id': '12345', - }, - name: 'codescene-test-project', - title: 'codescene-test-project', - description: 'A demo codescene-test repo', - links: [ - { - url: 'https://some-demo.com', - title: 'Demo', - icon: 'dashboard', - }, - ], - }, - apiVersion: 'backstage.io/v1alpha1', - kind: 'Component', - spec: { - type: 'website', - owner: 'swcoe', - lifecycle: 'experimental', - }, - relations: [ - { - type: 'ownedBy', - targetRef: 'group:default/swcoe', - target: { - kind: 'group', - namespace: 'default', - name: 'swcoe', - }, - }, - ], -}; - -describe('CodeSceneEntityPage', () => { - const server = setupServer(); - // Enable sane handlers for network requests - setupRequestMockHandlers(server); - let apis: TestApiRegistry; - - // setup mock response - beforeEach(() => { - server.use( - rest.get('/*', (_, res, ctx) => res(ctx.status(200), ctx.json({}))), - ); - - const config = new ConfigReader({ - codescene: { - baseUrl: 'www.fake-url.com', - }, - }); - const analysis: Analysis = { - id: 1, - name: 'codescene-test-project', - project_id: 12345, - readable_analysis_time: '2022-03-22', - summary: { - unique_issue_ids: 0, - issues_filtered_as_outliers: 0, - entities: 0, - commits_with_issue_ids: 0, - authors_count: 0, - active_authors_count: 0, - issues_with_cycle_time: 0, - commits: 0, - issue_ids_matched_to_issues: 0, - issues_classed_as_defects: 0, - issues_with_cost: 0, - }, - file_summary: [], - high_level_metrics: { - current_score: 0, - month_score: 0, - year_score: 0, - active_developers: 0, - lines_of_code: 0, - system_mastery: 0, - }, - }; - apis = TestApiRegistry.from( - [ - codesceneApiRef, - { - fetchLatestAnalysis: jest.fn(() => analysis), - } as unknown as CodeSceneApi, - ], - [configApiRef, config], - ); - }); - - it('should render', async () => { - const rendered = await renderInTestApp( - - - - - , - ); - expect(rendered.getByText(/codescene-test-project/i)).toBeInTheDocument(); - }); -}); diff --git a/plugins/codescene/src/components/CodeSceneEntityPage/CodeSceneEntityPage.tsx b/plugins/codescene/src/components/CodeSceneEntityPage/CodeSceneEntityPage.tsx deleted file mode 100644 index 19d2636fe9..0000000000 --- a/plugins/codescene/src/components/CodeSceneEntityPage/CodeSceneEntityPage.tsx +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright 2023 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 { - Content, - EmptyState, - GaugeCard, - Header, - InfoCard, - Page, - Progress, - SupportButton, - Table, - TableColumn, -} from '@backstage/core-components'; -import { configApiRef, useApi } from '@backstage/core-plugin-api'; -import { Grid, Typography } from '@material-ui/core'; -import Alert from '@material-ui/lab/Alert'; -import React from 'react'; -import { useEntity } from '@backstage/plugin-catalog-react'; -import useAsync from 'react-use/lib/useAsync'; -import { codesceneApiRef } from '../../api/api'; -import { Analysis } from '../../api/types'; -import { CodeHealthKpisCard } from '../CodeHealthKpisCard/CodeHealthKpisCard'; -import { MissingAnnotationEmptyState } from '@backstage/plugin-catalog-react'; -import { - getProjectAnnotation, - CODESCENE_PROJECT_ANNOTATION, - isCodeSceneAvailable, -} from '../../utils/commonUtil'; - -export const CodeSceneEntityPage = () => { - const { entity } = useEntity(); - const { projectId } = getProjectAnnotation(entity); - const codesceneApi = useApi(codesceneApiRef); - const config = useApi(configApiRef); - const { - value: analysis, - loading, - error, - } = useAsync(async (): Promise => { - return await codesceneApi.fetchLatestAnalysis(projectId); - }, []); - - if (loading) { - return ; - } else if (error) { - return {error.message}; - } else if (!analysis) { - return ( - - ); - } - - const columns: TableColumn[] = [ - { - title: 'Language', - field: 'language', - highlight: true, - }, - { - title: 'Files', - field: 'number_of_files', - type: 'numeric', - }, - { - title: 'Code', - field: 'code', - type: 'numeric', - }, - { - title: 'Comment', - field: 'comment', - type: 'numeric', - }, - ]; - - const fileSummaryTable = ( -
b.code - a.code)} - columns={columns} - title="File Summary" - /> - ); - - const codesceneHost = config.getString('codescene.baseUrl'); - const analysisPath = `${codesceneHost}/${projectId}/analyses/${analysis.id}`; - const analysisLink = { title: 'Check the analysis', link: analysisPath }; - - const analysisBody = ( - <> - - Active authors: {analysis.summary.active_authors_count} - - - Total authors: {analysis.summary.authors_count} - - - Commits: {analysis.summary.commits} - - - ); - - return isCodeSceneAvailable(entity) ? ( - -
- - See hidden risks and social patterns in your code. Prioritize and - reduce technical debt. - -
- - - - - - - - - - - - - - - {analysisBody} - - - - - {fileSummaryTable} - - -
- ) : ( - - ); -}; diff --git a/plugins/codescene/src/components/CodeSceneProjectDetailsPage/CodeSceneProjectDetailsPage.tsx b/plugins/codescene/src/components/CodeSceneProjectDetailsPage/CodeSceneProjectDetailsPage.tsx index 1197edb47e..dbacd919b4 100644 --- a/plugins/codescene/src/components/CodeSceneProjectDetailsPage/CodeSceneProjectDetailsPage.tsx +++ b/plugins/codescene/src/components/CodeSceneProjectDetailsPage/CodeSceneProjectDetailsPage.tsx @@ -20,48 +20,20 @@ import { Header, InfoCard, Page, - Progress, SupportButton, Table, TableColumn, } from '@backstage/core-components'; -import { configApiRef, useApi } from '@backstage/core-plugin-api'; +import { configApiRef, useApi, useApp } from '@backstage/core-plugin-api'; import { Grid, Typography } from '@material-ui/core'; import Alert from '@material-ui/lab/Alert'; import React from 'react'; import { useParams } from 'react-router-dom'; -import useAsync from 'react-use/lib/useAsync'; -import { codesceneApiRef } from '../../api/api'; -import { Analysis } from '../../api/types'; import { CodeHealthKpisCard } from '../CodeHealthKpisCard/CodeHealthKpisCard'; +import { useAnalyses } from '../../hooks/useAnalyses'; +import { Analysis } from '../../api/types'; -export const CodeSceneProjectDetailsPage = () => { - const params = useParams(); - const projectId = Number(params.projectId); - const codesceneApi = useApi(codesceneApiRef); - const config = useApi(configApiRef); - const { - value: analysis, - loading, - error, - } = useAsync(async (): Promise => { - return await codesceneApi.fetchLatestAnalysis(projectId); - }, []); - - if (loading) { - return ; - } else if (error) { - return {error.message}; - } else if (!analysis) { - return ( - - ); - } - +export const CodeSceneFileSummary = (props: Analysis) => { const columns: TableColumn[] = [ { title: 'Language', @@ -85,14 +57,36 @@ export const CodeSceneProjectDetailsPage = () => { }, ]; - const fileSummaryTable = ( + return (
b.code - a.code)} + data={props.file_summary.sort((a, b) => b.code - a.code)} columns={columns} title="File Summary" /> ); +}; + +export const CodeSceneProjectDetailsPage = () => { + const params = useParams(); + const projectId = Number(params.projectId); + const config = useApi(configApiRef); + const { analysis, loading, error } = useAnalyses(projectId); + const { Progress } = useApp().getComponents(); + + if (loading) { + return ; + } else if (error) { + return {error.message}; + } else if (!analysis) { + return ( + + ); + } const codesceneHost = config.getString('codescene.baseUrl'); const analysisPath = `${codesceneHost}/${projectId}/analyses/${analysis.id}`; @@ -150,7 +144,9 @@ export const CodeSceneProjectDetailsPage = () => { - {fileSummaryTable} + + + diff --git a/plugins/codescene/src/hooks/useAnalyses.ts b/plugins/codescene/src/hooks/useAnalyses.ts new file mode 100644 index 0000000000..9326b27641 --- /dev/null +++ b/plugins/codescene/src/hooks/useAnalyses.ts @@ -0,0 +1,34 @@ +/* + * Copyright 2023 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 { Analysis } from '../api/types'; +import { codesceneApiRef } from '../api/api'; +import { useApi } from '@backstage/core-plugin-api'; +import useAsync from 'react-use/lib/useAsync'; + +export const useAnalyses = (projectId: number) => { + const codesceneApi = useApi(codesceneApiRef); + + const { + value: analysis, + loading, + error, + } = useAsync(async (): Promise => { + return await codesceneApi.fetchLatestAnalysis(projectId); + }, []); + + return { analysis, loading, error }; +}; diff --git a/plugins/codescene/src/index.ts b/plugins/codescene/src/index.ts index 414af61d04..463086dd5e 100644 --- a/plugins/codescene/src/index.ts +++ b/plugins/codescene/src/index.ts @@ -17,7 +17,7 @@ export { codescenePlugin, CodeScenePage, CodeSceneProjectDetailsPage, - CodeSceneEntityPage, + CodeSceneEntityFileSummary, CodeSceneEntityKPICard, } from './plugin'; export { CodeSceneIcon } from './CodeSceneIcon'; diff --git a/plugins/codescene/src/plugin.ts b/plugins/codescene/src/plugin.ts index 70cb3fb2a5..49014568a5 100644 --- a/plugins/codescene/src/plugin.ts +++ b/plugins/codescene/src/plugin.ts @@ -18,6 +18,7 @@ import { createRoutableExtension, createApiFactory, discoveryApiRef, + createComponentExtension, } from '@backstage/core-plugin-api'; import { codesceneApiRef, CodeSceneClient } from './api/api'; import { rootRouteRef, projectDetailsRouteRef } from './routes'; @@ -72,26 +73,28 @@ export const CodeSceneProjectDetailsPage = codescenePlugin.provide( * @public */ export const CodeSceneEntityKPICard = codescenePlugin.provide( - createRoutableExtension({ + createComponentExtension({ name: 'CodeSceneEntityKPICard', - component: () => - import('./components/CodeSceneEntityKPICard').then( - m => m.CodeSceneEntityKPICard, - ), - mountPoint: rootRouteRef, + component: { + lazy: () => + import('./components/CodeSceneEntityKPICard').then( + m => m.CodeSceneEntityKPICard, + ), + }, }), ); /** * @public */ -export const CodeSceneEntityPage = codescenePlugin.provide( - createRoutableExtension({ - name: 'CodeSceneEntityPage', - component: () => - import('./components/CodeSceneEntityPage').then( - m => m.CodeSceneEntityPage, - ), - mountPoint: rootRouteRef, +export const CodeSceneEntityFileSummary = codescenePlugin.provide( + createComponentExtension({ + name: 'CodeSceneEntityFileSummary', + component: { + lazy: () => + import('./components/CodeSceneEntityFileSummary').then( + m => m.CodeSceneEntityFileSummary, + ), + }, }), ); From 4433efc0a6af7a83776960a124c0a3158470b685 Mon Sep 17 00:00:00 2001 From: blbose Date: Fri, 24 Nov 2023 01:33:42 +0530 Subject: [PATCH 4/6] fix: review comments on codescene entity changes Signed-off-by: blbose --- plugins/codescene/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/codescene/README.md b/plugins/codescene/README.md index 8c336bf74f..6770e34ddd 100644 --- a/plugins/codescene/README.md +++ b/plugins/codescene/README.md @@ -70,7 +70,7 @@ kind: Component metadata: name: backstage annotations: - codescene.io/project-id: + codescene.io/project-id: ``` ```tsx From 152a7ad76128cf2bd74a4ca23eebbf50cb2730a1 Mon Sep 17 00:00:00 2001 From: blbose Date: Fri, 23 Feb 2024 15:03:25 +0530 Subject: [PATCH 5/6] fix: merge conflicts on codescene entity changes Signed-off-by: blbose --- yarn.lock | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 151 insertions(+), 4 deletions(-) diff --git a/yarn.lock b/yarn.lock index 7105733663..2fbd25558d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3526,6 +3526,18 @@ __metadata: languageName: unknown linkType: soft +"@backstage/catalog-model@npm:^1.4.4": + version: 1.4.4 + resolution: "@backstage/catalog-model@npm:1.4.4" + dependencies: + "@backstage/errors": ^1.2.3 + "@backstage/types": ^1.1.1 + ajv: ^8.10.0 + lodash: ^4.17.21 + checksum: c04762fe638bd417dc0959a60d9e5bac47502046fed28ebba66e53e4da36a87ed9e90b4132d8a3d0f23a8e71bec4b1d8f4fdc3a32a7277ef5db2701e5f7a831a + languageName: node + linkType: hard + "@backstage/cli-common@workspace:^, @backstage/cli-common@workspace:packages/cli-common": version: 0.0.0-use.local resolution: "@backstage/cli-common@workspace:packages/cli-common" @@ -3883,6 +3895,57 @@ __metadata: languageName: node linkType: hard +"@backstage/core-components@npm:^0.14.0": + version: 0.14.0 + resolution: "@backstage/core-components@npm:0.14.0" + dependencies: + "@backstage/config": ^1.1.1 + "@backstage/core-plugin-api": ^1.9.0 + "@backstage/errors": ^1.2.3 + "@backstage/theme": ^0.5.1 + "@backstage/version-bridge": ^1.0.7 + "@date-io/core": ^1.3.13 + "@material-table/core": ^3.1.0 + "@material-ui/core": ^4.12.2 + "@material-ui/icons": ^4.9.1 + "@material-ui/lab": 4.0.0-alpha.61 + "@react-hookz/web": ^24.0.0 + "@types/react": ^16.13.1 || ^17.0.0 || ^18.0.0 + "@types/react-sparklines": ^1.7.0 + "@types/react-text-truncate": ^0.14.0 + ansi-regex: ^6.0.1 + classnames: ^2.2.6 + d3-selection: ^3.0.0 + d3-shape: ^3.0.0 + d3-zoom: ^3.0.0 + dagre: ^0.8.5 + linkify-react: 4.1.3 + linkifyjs: 4.1.3 + lodash: ^4.17.21 + pluralize: ^8.0.0 + qs: ^6.9.4 + rc-progress: 3.5.1 + react-helmet: 6.1.0 + react-hook-form: ^7.12.2 + react-idle-timer: 5.6.2 + react-markdown: ^8.0.0 + react-sparklines: ^1.7.0 + react-syntax-highlighter: ^15.4.5 + react-text-truncate: ^0.19.0 + react-use: ^17.3.2 + react-virtualized-auto-sizer: ^1.0.11 + react-window: ^1.8.6 + remark-gfm: ^3.0.1 + zen-observable: ^0.10.0 + zod: ^3.22.4 + peerDependencies: + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-router-dom: 6.0.0-beta.0 || ^6.3.0 + checksum: b6d48b71976361c13d8928e743699baad5788c619bd6e9ca536fbf8edafe1828b16002edc20207ddfce0858b760adf2748d4584beed7daa375afa8eefd827592 + languageName: node + linkType: hard + "@backstage/core-components@workspace:^, @backstage/core-components@workspace:packages/core-components": version: 0.0.0-use.local resolution: "@backstage/core-components@workspace:packages/core-components" @@ -5666,6 +5729,17 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-catalog-common@npm:^1.0.21": + version: 1.0.21 + resolution: "@backstage/plugin-catalog-common@npm:1.0.21" + dependencies: + "@backstage/catalog-model": ^1.4.4 + "@backstage/plugin-permission-common": ^0.7.12 + "@backstage/plugin-search-common": ^1.2.10 + checksum: 06570e20dddaf80f61d49d55ce1aa4a8213969742975902dd21f34cc6e37b0b2bc6e4d05b373425a16329a26bf682fd675ad77dcc60966bac0f4fa1a29e5bb59 + languageName: node + linkType: hard + "@backstage/plugin-catalog-graph@workspace:^, @backstage/plugin-catalog-graph@workspace:plugins/catalog-graph": version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-graph@workspace:plugins/catalog-graph" @@ -8834,6 +8908,16 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-search-common@npm:^1.2.10": + version: 1.2.10 + resolution: "@backstage/plugin-search-common@npm:1.2.10" + dependencies: + "@backstage/plugin-permission-common": ^0.7.12 + "@backstage/types": ^1.1.1 + checksum: e4faae5e46e34c352c6ecb7e981b9efb5c34c62263275cd32e035fe17a77c929e20200a90230e70958496a89b83139ac7168e476b8c1f6497052f1c48d3e1bdd + languageName: node + linkType: hard + "@backstage/plugin-search-common@workspace:^, @backstage/plugin-search-common@workspace:plugins/search-common": version: 0.0.0-use.local resolution: "@backstage/plugin-search-common@workspace:plugins/search-common" @@ -15431,6 +15515,13 @@ __metadata: languageName: node linkType: hard +"@remix-run/router@npm:1.15.1": + version: 1.15.1 + resolution: "@remix-run/router@npm:1.15.1" + checksum: 5c404e64a95da7d2a06811c15e8b213cd1079bca546d8a78a1626264ac0b71361b9ce93269bda7209a938e5a22c25993902841f81240c58eb7ed0934e1781197 + languageName: node + linkType: hard + "@remix-run/router@npm:1.3.2": version: 1.3.2 resolution: "@remix-run/router@npm:1.3.2" @@ -18485,6 +18576,13 @@ __metadata: languageName: node linkType: hard +"@types/estree@npm:*, @types/estree@npm:^1.0.0, @types/estree@npm:^1.0.5": + version: 1.0.5 + resolution: "@types/estree@npm:1.0.5" + checksum: dd8b5bed28e6213b7acd0fb665a84e693554d850b0df423ac8076cc3ad5823a6bc26b0251d080bdc545af83179ede51dd3f6fa78cad2c46ed1f29624ddf3e41a + languageName: node + linkType: hard + "@types/estree@npm:0.0.39": version: 0.0.39 resolution: "@types/estree@npm:0.0.39" @@ -20002,6 +20100,13 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/types@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/types@npm:6.21.0" + checksum: 9501b47d7403417af95fc1fb72b2038c5ac46feac0e1598a46bcb43e56a606c387e9dcd8a2a0abe174c91b509f2d2a8078b093786219eb9a01ab2fbf9ee7b684 + languageName: node + linkType: hard + "@typescript-eslint/typescript-estree@npm:5.59.8": version: 5.59.8 resolution: "@typescript-eslint/typescript-estree@npm:5.59.8" @@ -20074,6 +20179,24 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/utils@npm:^5.57.0": + version: 5.62.0 + resolution: "@typescript-eslint/utils@npm:5.62.0" + dependencies: + "@eslint-community/eslint-utils": ^4.2.0 + "@types/json-schema": ^7.0.9 + "@types/semver": ^7.3.12 + "@typescript-eslint/scope-manager": 5.62.0 + "@typescript-eslint/types": 5.62.0 + "@typescript-eslint/typescript-estree": 5.62.0 + eslint-scope: ^5.1.1 + semver: ^7.3.7 + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + checksum: ee9398c8c5db6d1da09463ca7bf36ed134361e20131ea354b2da16a5fdb6df9ba70c62a388d19f6eebb421af1786dbbd79ba95ddd6ab287324fc171c3e28d931 + languageName: node + linkType: hard + "@typescript-eslint/visitor-keys@npm:5.59.8": version: 5.59.8 resolution: "@typescript-eslint/visitor-keys@npm:5.59.8" @@ -38802,10 +38925,23 @@ __metadata: languageName: node linkType: hard -"protocol-buffers-schema@npm:^3.6.0": - version: 3.6.0 - resolution: "protocol-buffers-schema@npm:3.6.0" - checksum: 8713b5770f6745ddbcdf3bbd03ee020624d506233bb567927a6615a6f69a5bd620a5f49597f34f4115792b853a4c9cb9e2d5d6b930a1c04bf198023e45c1c349 +"protobufjs@npm:^7.2.6": + version: 7.2.6 + resolution: "protobufjs@npm:7.2.6" + dependencies: + "@protobufjs/aspromise": ^1.1.2 + "@protobufjs/base64": ^1.1.2 + "@protobufjs/codegen": ^2.0.4 + "@protobufjs/eventemitter": ^1.1.0 + "@protobufjs/fetch": ^1.1.0 + "@protobufjs/float": ^1.0.2 + "@protobufjs/inquire": ^1.1.0 + "@protobufjs/path": ^1.1.2 + "@protobufjs/pool": ^1.1.0 + "@protobufjs/utf8": ^1.1.0 + "@types/node": ">=13.7.0" + long: ^5.0.0 + checksum: 3c62e48f7d50017ac3b0dcd2a58e617cf858f9fba56a488bd48b9aa3482893a75540052dbcb3c12dfbaab42b1d04964611175faf06bdadcd33a4ebac982a511e languageName: node linkType: hard @@ -41349,6 +41485,17 @@ __metadata: languageName: node linkType: hard +"semver@npm:^7.1.1, semver@npm:^7.1.3, semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.3, semver@npm:^7.5.4": + version: 7.6.0 + resolution: "semver@npm:7.6.0" + dependencies: + lru-cache: ^6.0.0 + bin: + semver: bin/semver.js + checksum: 7427f05b70786c696640edc29fdd4bc33b2acf3bbe1740b955029044f80575fc664e1a512e4113c3af21e767154a94b4aa214bf6cd6e42a1f6dba5914e0b208c + languageName: node + linkType: hard + "send@npm:0.18.0": version: 0.18.0 resolution: "send@npm:0.18.0" From ac14957ce2d67a42da48d4efedcb539858b58c0b Mon Sep 17 00:00:00 2001 From: Scott Guymer Date: Fri, 23 Feb 2024 11:39:36 +0100 Subject: [PATCH 6/6] updated yarn lock Signed-off-by: Scott Guymer --- yarn.lock | 159 +++--------------------------------------------------- 1 file changed, 7 insertions(+), 152 deletions(-) diff --git a/yarn.lock b/yarn.lock index 2fbd25558d..89e5d47b40 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3526,18 +3526,6 @@ __metadata: languageName: unknown linkType: soft -"@backstage/catalog-model@npm:^1.4.4": - version: 1.4.4 - resolution: "@backstage/catalog-model@npm:1.4.4" - dependencies: - "@backstage/errors": ^1.2.3 - "@backstage/types": ^1.1.1 - ajv: ^8.10.0 - lodash: ^4.17.21 - checksum: c04762fe638bd417dc0959a60d9e5bac47502046fed28ebba66e53e4da36a87ed9e90b4132d8a3d0f23a8e71bec4b1d8f4fdc3a32a7277ef5db2701e5f7a831a - languageName: node - linkType: hard - "@backstage/cli-common@workspace:^, @backstage/cli-common@workspace:packages/cli-common": version: 0.0.0-use.local resolution: "@backstage/cli-common@workspace:packages/cli-common" @@ -3895,57 +3883,6 @@ __metadata: languageName: node linkType: hard -"@backstage/core-components@npm:^0.14.0": - version: 0.14.0 - resolution: "@backstage/core-components@npm:0.14.0" - dependencies: - "@backstage/config": ^1.1.1 - "@backstage/core-plugin-api": ^1.9.0 - "@backstage/errors": ^1.2.3 - "@backstage/theme": ^0.5.1 - "@backstage/version-bridge": ^1.0.7 - "@date-io/core": ^1.3.13 - "@material-table/core": ^3.1.0 - "@material-ui/core": ^4.12.2 - "@material-ui/icons": ^4.9.1 - "@material-ui/lab": 4.0.0-alpha.61 - "@react-hookz/web": ^24.0.0 - "@types/react": ^16.13.1 || ^17.0.0 || ^18.0.0 - "@types/react-sparklines": ^1.7.0 - "@types/react-text-truncate": ^0.14.0 - ansi-regex: ^6.0.1 - classnames: ^2.2.6 - d3-selection: ^3.0.0 - d3-shape: ^3.0.0 - d3-zoom: ^3.0.0 - dagre: ^0.8.5 - linkify-react: 4.1.3 - linkifyjs: 4.1.3 - lodash: ^4.17.21 - pluralize: ^8.0.0 - qs: ^6.9.4 - rc-progress: 3.5.1 - react-helmet: 6.1.0 - react-hook-form: ^7.12.2 - react-idle-timer: 5.6.2 - react-markdown: ^8.0.0 - react-sparklines: ^1.7.0 - react-syntax-highlighter: ^15.4.5 - react-text-truncate: ^0.19.0 - react-use: ^17.3.2 - react-virtualized-auto-sizer: ^1.0.11 - react-window: ^1.8.6 - remark-gfm: ^3.0.1 - zen-observable: ^0.10.0 - zod: ^3.22.4 - peerDependencies: - react: ^16.13.1 || ^17.0.0 || ^18.0.0 - react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 - react-router-dom: 6.0.0-beta.0 || ^6.3.0 - checksum: b6d48b71976361c13d8928e743699baad5788c619bd6e9ca536fbf8edafe1828b16002edc20207ddfce0858b760adf2748d4584beed7daa375afa8eefd827592 - languageName: node - linkType: hard - "@backstage/core-components@workspace:^, @backstage/core-components@workspace:packages/core-components": version: 0.0.0-use.local resolution: "@backstage/core-components@workspace:packages/core-components" @@ -5729,17 +5666,6 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-catalog-common@npm:^1.0.21": - version: 1.0.21 - resolution: "@backstage/plugin-catalog-common@npm:1.0.21" - dependencies: - "@backstage/catalog-model": ^1.4.4 - "@backstage/plugin-permission-common": ^0.7.12 - "@backstage/plugin-search-common": ^1.2.10 - checksum: 06570e20dddaf80f61d49d55ce1aa4a8213969742975902dd21f34cc6e37b0b2bc6e4d05b373425a16329a26bf682fd675ad77dcc60966bac0f4fa1a29e5bb59 - languageName: node - linkType: hard - "@backstage/plugin-catalog-graph@workspace:^, @backstage/plugin-catalog-graph@workspace:plugins/catalog-graph": version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-graph@workspace:plugins/catalog-graph" @@ -6157,12 +6083,14 @@ __metadata: "@backstage/errors": "workspace:^" "@backstage/plugin-catalog-react": "workspace:^" "@backstage/test-utils": "workspace:^" + "@backstage/theme": "workspace:^" "@material-ui/core": ^4.12.2 "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 "@testing-library/react": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 || ^18.0.0 + luxon: ^3.4.4 msw: ^1.0.0 rc-progress: 3.5.1 react-use: ^17.2.4 @@ -8908,16 +8836,6 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-search-common@npm:^1.2.10": - version: 1.2.10 - resolution: "@backstage/plugin-search-common@npm:1.2.10" - dependencies: - "@backstage/plugin-permission-common": ^0.7.12 - "@backstage/types": ^1.1.1 - checksum: e4faae5e46e34c352c6ecb7e981b9efb5c34c62263275cd32e035fe17a77c929e20200a90230e70958496a89b83139ac7168e476b8c1f6497052f1c48d3e1bdd - languageName: node - linkType: hard - "@backstage/plugin-search-common@workspace:^, @backstage/plugin-search-common@workspace:plugins/search-common": version: 0.0.0-use.local resolution: "@backstage/plugin-search-common@workspace:plugins/search-common" @@ -15515,13 +15433,6 @@ __metadata: languageName: node linkType: hard -"@remix-run/router@npm:1.15.1": - version: 1.15.1 - resolution: "@remix-run/router@npm:1.15.1" - checksum: 5c404e64a95da7d2a06811c15e8b213cd1079bca546d8a78a1626264ac0b71361b9ce93269bda7209a938e5a22c25993902841f81240c58eb7ed0934e1781197 - languageName: node - linkType: hard - "@remix-run/router@npm:1.3.2": version: 1.3.2 resolution: "@remix-run/router@npm:1.3.2" @@ -18576,13 +18487,6 @@ __metadata: languageName: node linkType: hard -"@types/estree@npm:*, @types/estree@npm:^1.0.0, @types/estree@npm:^1.0.5": - version: 1.0.5 - resolution: "@types/estree@npm:1.0.5" - checksum: dd8b5bed28e6213b7acd0fb665a84e693554d850b0df423ac8076cc3ad5823a6bc26b0251d080bdc545af83179ede51dd3f6fa78cad2c46ed1f29624ddf3e41a - languageName: node - linkType: hard - "@types/estree@npm:0.0.39": version: 0.0.39 resolution: "@types/estree@npm:0.0.39" @@ -20100,13 +20004,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/types@npm:6.21.0": - version: 6.21.0 - resolution: "@typescript-eslint/types@npm:6.21.0" - checksum: 9501b47d7403417af95fc1fb72b2038c5ac46feac0e1598a46bcb43e56a606c387e9dcd8a2a0abe174c91b509f2d2a8078b093786219eb9a01ab2fbf9ee7b684 - languageName: node - linkType: hard - "@typescript-eslint/typescript-estree@npm:5.59.8": version: 5.59.8 resolution: "@typescript-eslint/typescript-estree@npm:5.59.8" @@ -20179,24 +20076,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/utils@npm:^5.57.0": - version: 5.62.0 - resolution: "@typescript-eslint/utils@npm:5.62.0" - dependencies: - "@eslint-community/eslint-utils": ^4.2.0 - "@types/json-schema": ^7.0.9 - "@types/semver": ^7.3.12 - "@typescript-eslint/scope-manager": 5.62.0 - "@typescript-eslint/types": 5.62.0 - "@typescript-eslint/typescript-estree": 5.62.0 - eslint-scope: ^5.1.1 - semver: ^7.3.7 - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - checksum: ee9398c8c5db6d1da09463ca7bf36ed134361e20131ea354b2da16a5fdb6df9ba70c62a388d19f6eebb421af1786dbbd79ba95ddd6ab287324fc171c3e28d931 - languageName: node - linkType: hard - "@typescript-eslint/visitor-keys@npm:5.59.8": version: 5.59.8 resolution: "@typescript-eslint/visitor-keys@npm:5.59.8" @@ -34048,7 +33927,7 @@ __metadata: languageName: node linkType: hard -"luxon@npm:^3.0.0, luxon@npm:^3.3.0, luxon@npm:^3.4.3, luxon@npm:~3.4.0": +"luxon@npm:^3.0.0, luxon@npm:^3.3.0, luxon@npm:^3.4.3, luxon@npm:^3.4.4, luxon@npm:~3.4.0": version: 3.4.4 resolution: "luxon@npm:3.4.4" checksum: 36c1f99c4796ee4bfddf7dc94fa87815add43ebc44c8934c924946260a58512f0fd2743a629302885df7f35ccbd2d13f178c15df046d0e3b6eb71db178f1c60c @@ -38925,23 +38804,10 @@ __metadata: languageName: node linkType: hard -"protobufjs@npm:^7.2.6": - version: 7.2.6 - resolution: "protobufjs@npm:7.2.6" - dependencies: - "@protobufjs/aspromise": ^1.1.2 - "@protobufjs/base64": ^1.1.2 - "@protobufjs/codegen": ^2.0.4 - "@protobufjs/eventemitter": ^1.1.0 - "@protobufjs/fetch": ^1.1.0 - "@protobufjs/float": ^1.0.2 - "@protobufjs/inquire": ^1.1.0 - "@protobufjs/path": ^1.1.2 - "@protobufjs/pool": ^1.1.0 - "@protobufjs/utf8": ^1.1.0 - "@types/node": ">=13.7.0" - long: ^5.0.0 - checksum: 3c62e48f7d50017ac3b0dcd2a58e617cf858f9fba56a488bd48b9aa3482893a75540052dbcb3c12dfbaab42b1d04964611175faf06bdadcd33a4ebac982a511e +"protocol-buffers-schema@npm:^3.6.0": + version: 3.6.0 + resolution: "protocol-buffers-schema@npm:3.6.0" + checksum: 8713b5770f6745ddbcdf3bbd03ee020624d506233bb567927a6615a6f69a5bd620a5f49597f34f4115792b853a4c9cb9e2d5d6b930a1c04bf198023e45c1c349 languageName: node linkType: hard @@ -41485,17 +41351,6 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.1.1, semver@npm:^7.1.3, semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.3, semver@npm:^7.5.4": - version: 7.6.0 - resolution: "semver@npm:7.6.0" - dependencies: - lru-cache: ^6.0.0 - bin: - semver: bin/semver.js - checksum: 7427f05b70786c696640edc29fdd4bc33b2acf3bbe1740b955029044f80575fc664e1a512e4113c3af21e767154a94b4aa214bf6cd6e42a1f6dba5914e0b208c - languageName: node - linkType: hard - "send@npm:0.18.0": version: 0.18.0 resolution: "send@npm:0.18.0"