diff --git a/workspaces/npm/.changeset/polite-houses-flow.md b/workspaces/npm/.changeset/polite-houses-flow.md new file mode 100644 index 0000000000..5bb17a12cb --- /dev/null +++ b/workspaces/npm/.changeset/polite-houses-flow.md @@ -0,0 +1,7 @@ +--- +'@backstage-community/plugin-npm-backend': minor +'@backstage-community/plugin-npm-common': minor +'@backstage-community/plugin-npm': minor +--- + +Added support for custom and private npm registries like GitHub and GitLab via a new backend plugin. Other npm registries that works with the npm cli should work as well. diff --git a/workspaces/npm/README.md b/workspaces/npm/README.md index 94044a3fa6..d3bfd2b310 100644 --- a/workspaces/npm/README.md +++ b/workspaces/npm/README.md @@ -1,16 +1,324 @@ -# [Backstage](https://backstage.io) +# npm plugin for Backstage -This is your newly scaffolded Backstage App, Good Luck! +A Backstage plugin that shows information and latest releases/versions +from a npm registry for catalog entities. -To start the app, run: +The current version can show two cards and one additional tab for an catalog entity. -```sh -yarn install -yarn dev +1. The "Npm info card" shows general information like the latest version, description, etc. +2. The "Npm release overview card" shows the latest tags of an npm package. +3. The "Npm release tab" shows the version hisory in detail. + +## Screenshots + +### Npm info card + +![Screenshot](docs/npm-info-card.png) + +### Npm release overview card + +![Screenshot](docs/npm-release-overview-card.png) + +### Extended catalog entity overview tab (example) + +![Screenshot](docs/catalog-entity-overview-tab.png) + +### New catalog entity npm release tab + +![Screenshot](docs/catalog-entity-npm-release-tab.png) + +## Usage + +### Enable npm cards for a catalog entity + +To enable the different npm cards you must add the `npm/package` annotation +with the name of the npm package: + +```yaml +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: react + annotations: + npm/package: react +``` + +### Use other npm tag then `latest` + +The "npm info" card shows the information of the latest 'stable' npm release +and use the common `latest` tag by default. This could be changed with `npm/stable-tag`: + +```yaml +# catalog-info.yaml +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: react + annotations: + npm/package: react + npm/stable-tag: latest, stable, next, etc. ``` -To generate knip reports for this app, run: +### Use a custom registry + +To use another npm registry you need to specific a registry name in your +catalog entity that exists in your `app-config.yaml`. -```sh -yarn backstage-repo-tools knip-reports +```yaml +# catalog-info.yaml +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: react + annotations: + npm/package: another-package + npm/registry: github ``` + +```yaml +# app-config.yaml +npm: + registries: + - name: github + url: https://npm.pkg.github.com + token: ghp_... +``` + +## Installation + +To show information from a private package or an alternative npm registry +you must install also the backend plugin and [configure it](./registries.md). + +### Frontend plugin + +1. Install the frontend dependency: + + ```sh + yarn workspace app add @backstage-community/plugin-npm + ``` + +2. Add cards based on your needs to `packages/app/src/components/catalog/EntityPage.tsx`: + + After all other imports: + + ```tsx + import { + isNpmAvailable, + EntityNpmInfoCard, + EntityNpmReleaseOverviewCard, + EntityNpmReleaseTableCard, + } from '@backstage-community/plugin-npm'; + ``` + +3. Add to `const overviewContent` after `EntityAboutCard`: + + ```tsx + + + + + + + + + + + + + ``` + +4. Add to `const serviceEntityPage` and `const websiteEntityPage` after the `/ci-cd` case + and to `const defaultEntityPage` between the `/` and `/docs` routecase. + + ```tsx + + + + ``` + +### Alternative: Use the new frontend system (alpha) + +For early adaopters of the new frontend system. + +Your Backstage frontend app must use that new frontend system which isn't the default at the moment. + +1. Install the frontend dependency: + + ```sh + yarn workspace app-next add @backstage-community/plugin-npm + ``` + +2. Add the package to your `packages/app[-next]/src/App.tsx`. + + ```tsx + import npmPlugin from '@backstage-community/plugin-npm/alpha'; + ``` + + And extend your createApp: + + ```tsx + export const app = createApp({ + features: [ + catalogPlugin, + catalogImportPlugin, + userSettingsPlugin, + npmPlugin, + // ... + ], + }); + ``` + +### Optional: Backend plugin (req. for private packages or alternative registries) + +1. Install the backend plugin: + + ```sh + yarn workspace backend add @backstage-community/plugin-npm + ``` + +2. Add it to `packages/backend/src/index.ts`: + + ```tsx + backend.add(import('@backstage-community/plugin-npm-backend')); + ``` + +3. The backend is only used for catalog entities with a registry by default. + + If no `npm/registry` annotation is defined, the npm plugin loads the + information directly from the frontend. + (The browser of the user will connect to https://registry.npmjs.com.) + + You can enforce using the backend by defining a default registry: + + ```yaml + # app-config.yaml + # optional to enforce the frontend to use the backend + npm: + defaultRegistry: npmjs + ``` + +For more information, please checkout the [Registries](./registries.md) documentation. + +### Optional: Test with plugin-example catalog entities + +For testing purpose you can import this catalog entities: + +```yaml +# catalog-info.yaml +catalog: + locations: + - type: url + target: https://github.com/backstage/community-plugins/blob/main/workspaces/npm/examples/entities.yaml + rules: + - allow: [System, Component] +``` + +## Registries + +The npm plugin supports custom and private registries starting with v1.2. + +### Default Configuration + +The plugin loads information by default from https://registry.npmjs.com + +This works without any additional configuration in your `app-config.yaml` +but only for public npm packages. + +```yaml +npm: + registries: + - name: npmjs + url: https://registry.npmjs.com +``` + +### Use an auth token for npmjs + +To load information from another registry or to load information +from a private package, you must [install the backend](./install.md). + +The catalog entity `npm/registry` annotation must be defined and match +one of the registries in the `app-config.yaml`: + +Example: + +```yaml +# catalog-info.yaml +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: a-component + annotations: + npm/package: private-package + npm/registry: npmjs +``` + +```yaml +# app-config.yaml +npm: + registries: + - name: npmjs + url: https://registry.npmjs.com + token: ... +``` + +The `npm/registry: npmjs` annotation is required to use the npm backend. + +Alternativly you can setup a default registry (also for npmjs): + +```yaml +# app-config.yaml +npm: + defaultRegistry: npmjs +``` + +### Use an alternative registry + +Entity example: + +```yaml +# catalog-info.yaml +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: a-component + annotations: + npm/package: private-package + npm/registry: private-registry +``` + +```yaml +# app-config.yaml +npm: + registries: + - name: private-registry + url: https://... + token: ... +``` + +### Use GitHub npm registry + +The GitHub npm registry reqires also a GitHub token for public entries. + +You need to create a token at https://github.com/settings/tokens + +```yaml +# app-config.yaml +npm: + registries: + - name: github + url: https://npm.pkg.github.com + token: ghp_... +``` + +### Other npm registries + +Other npm registries should work the same way. + +Please let us know if we should mention here another registry or +if you find any issue. + +You can create a new [Issues on GitHub](https://github.com/backstage/community-plugins/issues/new?assignees=&labels=bug&projects=&template=1-bug.yaml&title=🐛+Npm%3A+) diff --git a/workspaces/npm/app-config.yaml b/workspaces/npm/app-config.yaml index efa9f5f544..cd88cfdb71 100644 --- a/workspaces/npm/app-config.yaml +++ b/workspaces/npm/app-config.yaml @@ -1,9 +1,9 @@ app: - title: Npm Plugin Example App + title: npm plugin example app baseUrl: http://localhost:3000 organization: - name: Npm Plugin Example + name: npm plugin example backend: # Used for enabling authentication, secret is shared by all backend plugins @@ -78,21 +78,28 @@ catalog: rules: - allow: [Component, System, API, Resource, Location] locations: - # Local example data, file locations are relative to the backend process, typically `packages/backend` + # Plugin itself for techdocs - type: file - target: ../../examples/entities.yaml - - # Local example template + target: ../../catalog-info.yaml - type: file - target: ../../examples/template/template.yaml - rules: - - allow: [Template] - - # Local example organizational data + target: ../../plugins/npm/catalog-info.yaml + - type: file + target: ../../plugins/npm-backend/catalog-info.yaml + - type: file + target: ../../plugins/npm-common/catalog-info.yaml + # Local example data - type: file target: ../../examples/org.yaml rules: - allow: [User, Group] + - type: file + target: ../../examples/system.yaml + - type: file + target: ../../examples/npmjs-examples.yaml + - type: file + target: ../../examples/github-examples.yaml + - type: file + target: ../../examples/gitlab-examples.yaml ## Uncomment these lines to add more example data # - type: url @@ -104,6 +111,16 @@ catalog: # rules: # - allow: [User, Group] +npm: + defaultRegistry: npmjs + registries: + - name: npmjs + url: https://registry.npmjs.com + - name: github + url: https://npm.pkg.github.com + - name: gitlab + url: https://gitlab.com/api/v4/packages/npm + # see https://backstage.io/docs/permissions/getting-started for more on the permission framework permission: # setting this to `false` will disable permissions diff --git a/workspaces/npm/catalog-info.yaml b/workspaces/npm/catalog-info.yaml index 5ba616ec3b..58223293bc 100644 --- a/workspaces/npm/catalog-info.yaml +++ b/workspaces/npm/catalog-info.yaml @@ -1,10 +1,16 @@ apiVersion: backstage.io/v1alpha1 kind: Component metadata: - name: backstage-plugin-npm-workspace - title: 'Backstage Community Npm Plugin' + name: backstage-plugin-npm + title: npm plugin for Backstage description: A Backstage plugin that shows meta info and latest versions from a npm registry + annotations: + backstage.io/techdocs-ref: dir:. + links: + - url: https://github.com/backstage/community-plugins/tree/main/workspaces/npm + title: GitHub + icon: sourcecode spec: - lifecycle: experimental + lifecycle: production type: backstage-plugin owner: maintainers diff --git a/workspaces/npm/plugins/npm/docs/catalog-entity-npm-release-tab.png b/workspaces/npm/docs/catalog-entity-npm-release-tab.png similarity index 100% rename from workspaces/npm/plugins/npm/docs/catalog-entity-npm-release-tab.png rename to workspaces/npm/docs/catalog-entity-npm-release-tab.png diff --git a/workspaces/npm/plugins/npm/docs/catalog-entity-overview-tab.png b/workspaces/npm/docs/catalog-entity-overview-tab.png similarity index 100% rename from workspaces/npm/plugins/npm/docs/catalog-entity-overview-tab.png rename to workspaces/npm/docs/catalog-entity-overview-tab.png diff --git a/workspaces/npm/docs/index.md b/workspaces/npm/docs/index.md new file mode 100644 index 0000000000..c2a29b77aa --- /dev/null +++ b/workspaces/npm/docs/index.md @@ -0,0 +1,27 @@ +# About + +The npm plugin for Backstage can show different information from a npm registry in your software catalog. + +The current version can show two cards and one additional tab for an catalog entity. + +1. The "Npm info card" shows general information like the latest version, description, etc. +2. The "Npm release overview card" shows the latest tags of an npm package. +3. The "Npm release tab" shows the version hisory in detail. + +## Screenshots + +### Npm info card + +![Screenshot](https://raw.githubusercontent.com/backstage/community-plugins/main/workspaces/npm/plugins/npm/docs/npm-info-card.png) + +### Npm release overview card + +![Screenshot](https://raw.githubusercontent.com/backstage/community-plugins/main/workspaces/npm/plugins/npm/docs/npm-release-overview-card.png) + +### Extended catalog entity overview tab (example) + +![Screenshot](https://raw.githubusercontent.com/backstage/community-plugins/main/workspaces/npm/plugins/npm/docs/catalog-entity-overview-tab.png) + +### New catalog entity npm release tab + +![Screenshot](https://raw.githubusercontent.com/backstage/community-plugins/main/workspaces/npm/plugins/npm/docs/catalog-entity-npm-release-tab.png) diff --git a/workspaces/npm/docs/install.md b/workspaces/npm/docs/install.md new file mode 100644 index 0000000000..1a7b2eb7ee --- /dev/null +++ b/workspaces/npm/docs/install.md @@ -0,0 +1,132 @@ +# Installation + +To show information from a private package or an alternative npm registry +you must install also the backend plugin and [configure it](./registries.md). + +## Frontend plugin + +1. Install the frontend dependency: + + ```sh + yarn workspace app add @backstage-community/plugin-npm + ``` + +2. Add cards based on your needs to `packages/app/src/components/catalog/EntityPage.tsx`: + + After all other imports: + + ```tsx + import { + isNpmAvailable, + EntityNpmInfoCard, + EntityNpmReleaseOverviewCard, + EntityNpmReleaseTableCard, + } from '@backstage-community/plugin-npm'; + ``` + +3. Add to `const overviewContent` after `EntityAboutCard`: + + ```tsx + <EntitySwitch> + <EntitySwitch.Case if={isNpmAvailable}> + <Grid container item md={6} xs={12}> + <Grid item md={12}> + <EntityNpmInfoCard /> + </Grid> + <Grid item md={12}> + <EntityNpmReleaseOverviewCard /> + </Grid> + </Grid> + </EntitySwitch.Case> + </EntitySwitch> + ``` + +4. Add to `const serviceEntityPage` and `const websiteEntityPage` after the `/ci-cd` case + and to `const defaultEntityPage` between the `/` and `/docs` routecase. + + ```tsx + <EntityLayout.Route + if={isNpmAvailable} + path="/npm-releases" + title="NPM Releases" + > + <EntityNpmReleaseTableCard /> + </EntityLayout.Route> + ``` + +## Alternative: Use the new frontend system (alpha) + +For early adaopters of the new frontend system. + +Your Backstage frontend app must use that new frontend system which isn't the default at the moment. + +1. Install the frontend dependency: + + ```sh + yarn workspace app-next add @backstage-community/plugin-npm + ``` + +2. Add the package to your `packages/app[-next]/src/App.tsx`. + + ```tsx + import npmPlugin from '@backstage-community/plugin-npm/alpha'; + ``` + + And extend your createApp: + + ```tsx + export const app = createApp({ + features: [ + catalogPlugin, + catalogImportPlugin, + userSettingsPlugin, + npmPlugin, + // ... + ], + }); + ``` + +## Optional: Backend plugin (req. for private packages or alternative registries) + +1. Install the backend plugin: + + ```sh + yarn workspace backend add @backstage-community/plugin-npm + ``` + +2. Add it to `packages/backend/src/index.ts`: + + ```tsx + backend.add(import('@backstage-community/plugin-npm-backend')); + ``` + +3. The backend is only used for catalog entities with a registry by default. + + If no `npm/registry` annotation is defined, the npm plugin loads the + information directly from the frontend. + (The browser of the user will connect to https://registry.npmjs.com.) + + You can enforce using the backend by defining a default registry: + + ```yaml + # app-config.yaml + # optional to enforce the frontend to use the backend + npm: + defaultRegistry: npmjs + ``` + +For more information, please checkout the [Registries](./registries.md) documentation. + +## Optional: Test with plugin-example catalog entities + +For testing purpose you can import this catalog entities: + +```yaml +# catalog-info.yaml +catalog: + locations: + - type: url + target: https://github.com/backstage/community-plugins/blob/main/workspaces/npm/examples/entities.yaml + rules: + - allow: [System, Component] +``` diff --git a/workspaces/npm/plugins/npm/docs/npm-info-card.png b/workspaces/npm/docs/npm-info-card.png similarity index 100% rename from workspaces/npm/plugins/npm/docs/npm-info-card.png rename to workspaces/npm/docs/npm-info-card.png diff --git a/workspaces/npm/plugins/npm/docs/npm-release-overview-card.png b/workspaces/npm/docs/npm-release-overview-card.png similarity index 100% rename from workspaces/npm/plugins/npm/docs/npm-release-overview-card.png rename to workspaces/npm/docs/npm-release-overview-card.png diff --git a/workspaces/npm/docs/registries.md b/workspaces/npm/docs/registries.md new file mode 100644 index 0000000000..467a433e23 --- /dev/null +++ b/workspaces/npm/docs/registries.md @@ -0,0 +1,120 @@ +# Registries + +The npm plugin supports custom and private registries starting with v1.2. + +## Default Configuration + +The plugin loads information by default from https://registry.npmjs.com + +This works without any additional configuration in your `app-config.yaml` +but only for public npm packages. + +```yaml +npm: + registries: + - name: npmjs + url: https://registry.npmjs.com +``` + +## Use an auth token for npmjs + +To load information from another registry or to load information +from a private package, you must [install the backend](./install.md). + +The catalog entity `npm/registry` annotation must be defined and match +one of the registries in the `app-config.yaml`: + +Example: + +```yaml +# catalog-info.yaml +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: a-component + annotations: + npm/package: private-package + npm/registry: npmjs +``` + +```yaml +# app-config.yaml +npm: + registries: + - name: npmjs + url: https://registry.npmjs.com + token: ... +``` + +The `npm/registry: npmjs` annotation is required to use the npm backend. + +Alternativly you can setup a default registry (also for npmjs): + +```yaml +# app-config.yaml +npm: + defaultRegistry: npmjs +``` + +## Use an alternative registry + +Entity example: + +```yaml +# catalog-info.yaml +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: a-component + annotations: + npm/package: private-package + npm/registry: private-registry +``` + +```yaml +# app-config.yaml +npm: + registries: + - name: private-registry + url: https://... + token: ... +``` + +## Use GitHub npm registry + +The GitHub npm registry requires also a GitHub token for public packages. + +You need to create a token at https://github.com/settings/tokens + +```yaml +# app-config.yaml +npm: + registries: + - name: github + url: https://npm.pkg.github.com + token: ghp_... +``` + +## Use GitLab npm registry + +The GitLab npm registry might requires a token for private packages. + +You need to create a token at https://github.com/settings/tokens + +```yaml +# app-config.yaml +npm: + registries: + - name: gitlab + url: https://gitlab.com/api/v4/packages/npm + token: ... +``` + +## Other npm registries + +Other npm registries should work the same way. + +Please let us know if we should mention here another registry or +if you find any issue. + +You can create a new [Issue on GitHub](https://github.com/backstage/community-plugins/issues/new?assignees=&labels=bug&projects=&template=1-bug.yaml&title=🐛+Npm%3A+<Title>) diff --git a/workspaces/npm/docs/usage.md b/workspaces/npm/docs/usage.md new file mode 100644 index 0000000000..16bbe703e8 --- /dev/null +++ b/workspaces/npm/docs/usage.md @@ -0,0 +1,58 @@ +# Usage + +## Enable npm cards for a catalog entity + +To enable the different npm cards you must add the `npm/package` annotation +with the name of the npm package: + +```yaml +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: react + annotations: + npm/package: react +``` + +## Use other npm tag then `latest` + +The "npm info" card shows the information of the latest 'stable' npm release +and use the common `latest` tag by default. This could be changed with `npm/stable-tag`: + +```yaml +# catalog-info.yaml +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: react + annotations: + npm/package: react + npm/stable-tag: latest, stable, next, etc. +``` + +## Use a custom registry + +To use another npm registry you need to specific a registry name in your +catalog entity that exists in your `app-config.yaml`. + +```yaml +# catalog-info.yaml +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: react + annotations: + npm/package: another-package + npm/registry: github +``` + +```yaml +# app-config.yaml +npm: + registries: + - name: github + url: https://npm.pkg.github.com + token: ghp_... +``` + +For more informations and scenarios see [Registries](./registries.md). diff --git a/workspaces/npm/examples/github-examples.yaml b/workspaces/npm/examples/github-examples.yaml new file mode 100644 index 0000000000..464fc41010 --- /dev/null +++ b/workspaces/npm/examples/github-examples.yaml @@ -0,0 +1,21 @@ +--- +# https://backstage.io/docs/features/software-catalog/descriptor-format#kind-component +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: github-example + annotations: + npm/registry: github + npm/package: '@github-packages-examples/npm-publish' + links: + - url: https://github.com/github-packages-examples + title: GitHub org + - url: https://github.com/github-packages-examples/npm-publish + title: GitHub repo + - url: https://github.com/github-packages-examples/npm-publish/pkgs/npm/npm-publish + title: GitHub npm packages +spec: + type: library + lifecycle: production + owner: guests + system: backstage diff --git a/workspaces/npm/examples/gitlab-examples.yaml b/workspaces/npm/examples/gitlab-examples.yaml new file mode 100644 index 0000000000..ad770b64dc --- /dev/null +++ b/workspaces/npm/examples/gitlab-examples.yaml @@ -0,0 +1,21 @@ +--- +# https://backstage.io/docs/features/software-catalog/descriptor-format#kind-component +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: gitlab-example + annotations: + npm/registry: gitlab + npm/package: '@gitlab-examples/semantic-release-npm' + links: + - url: https://gitlab.com/gitlab-examples + title: GitLab org + - url: https://gitlab.com/gitlab-examples/semantic-release-npm + title: GitLab repo + - url: https://gitlab.com/gitlab-examples/semantic-release-npm/-/packages + title: GitLab npm packages +spec: + type: library + lifecycle: production + owner: guests + system: backstage diff --git a/workspaces/npm/examples/entities.yaml b/workspaces/npm/examples/npmjs-examples.yaml similarity index 94% rename from workspaces/npm/examples/entities.yaml rename to workspaces/npm/examples/npmjs-examples.yaml index 773b139043..3325199344 100644 --- a/workspaces/npm/examples/entities.yaml +++ b/workspaces/npm/examples/npmjs-examples.yaml @@ -1,12 +1,4 @@ --- -# https://backstage.io/docs/features/software-catalog/descriptor-format#kind-system -apiVersion: backstage.io/v1alpha1 -kind: System -metadata: - name: backstage -spec: - owner: guests ---- # https://backstage.io/docs/features/software-catalog/descriptor-format#kind-component apiVersion: backstage.io/v1alpha1 kind: Component @@ -14,6 +6,7 @@ metadata: name: backstage-catalog-model annotations: npm/package: '@backstage/catalog-model' + npm/show-tags: latest, next spec: type: library lifecycle: production @@ -27,6 +20,7 @@ metadata: name: backstage-catalog-client annotations: npm/package: '@backstage/catalog-client' + npm/show-tags: latest, next spec: type: library lifecycle: production @@ -42,6 +36,7 @@ metadata: name: backstage-plugin-catalog-common annotations: npm/package: '@backstage/plugin-catalog-common' + npm/show-tags: latest, next spec: type: library lifecycle: production @@ -57,6 +52,7 @@ metadata: name: backstage-plugin-catalog-node annotations: npm/package: '@backstage/plugin-catalog-node' + npm/show-tags: latest, next spec: type: library lifecycle: production @@ -72,6 +68,7 @@ metadata: name: backstage-plugin-catalog-react annotations: npm/package: '@backstage/plugin-catalog-react' + npm/show-tags: latest, next spec: type: library lifecycle: production @@ -89,6 +86,7 @@ metadata: name: backstage-plugin-catalog annotations: npm/package: '@backstage/plugin-catalog' + npm/show-tags: latest, next spec: type: website lifecycle: production diff --git a/workspaces/npm/examples/system.yaml b/workspaces/npm/examples/system.yaml new file mode 100644 index 0000000000..f73504455e --- /dev/null +++ b/workspaces/npm/examples/system.yaml @@ -0,0 +1,8 @@ +--- +# https://backstage.io/docs/features/software-catalog/descriptor-format#kind-system +apiVersion: backstage.io/v1alpha1 +kind: System +metadata: + name: backstage +spec: + owner: guests diff --git a/workspaces/npm/examples/template/content/catalog-info.yaml b/workspaces/npm/examples/template/content/catalog-info.yaml deleted file mode 100644 index d4ccca42ef..0000000000 --- a/workspaces/npm/examples/template/content/catalog-info.yaml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: backstage.io/v1alpha1 -kind: Component -metadata: - name: ${{ values.name | dump }} -spec: - type: service - owner: user:guest - lifecycle: experimental diff --git a/workspaces/npm/examples/template/content/package.json b/workspaces/npm/examples/template/content/package.json deleted file mode 100644 index 86f968a73b..0000000000 --- a/workspaces/npm/examples/template/content/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "${{ values.name }}", - "private": true, - "dependencies": {} -} diff --git a/workspaces/npm/examples/template/template.yaml b/workspaces/npm/examples/template/template.yaml deleted file mode 100644 index 33f262b49c..0000000000 --- a/workspaces/npm/examples/template/template.yaml +++ /dev/null @@ -1,74 +0,0 @@ -apiVersion: scaffolder.backstage.io/v1beta3 -# https://backstage.io/docs/features/software-catalog/descriptor-format#kind-template -kind: Template -metadata: - name: example-nodejs-template - title: Example Node.js Template - description: An example template for the scaffolder that creates a simple Node.js service -spec: - owner: user:guest - type: service - - # These parameters are used to generate the input form in the frontend, and are - # used to gather input data for the execution of the template. - parameters: - - title: Fill in some steps - required: - - name - properties: - name: - title: Name - type: string - description: Unique name of the component - ui:autofocus: true - ui:options: - rows: 5 - - title: Choose a location - required: - - repoUrl - properties: - repoUrl: - title: Repository Location - type: string - ui:field: RepoUrlPicker - ui:options: - allowedHosts: - - github.com - - # These steps are executed in the scaffolder backend, using data that we gathered - # via the parameters above. - steps: - # Each step executes an action, in this case one templates files into the working directory. - - id: fetch-base - name: Fetch Base - action: fetch:template - input: - url: ./content - values: - name: ${{ parameters.name }} - - # This step publishes the contents of the working directory to GitHub. - - id: publish - name: Publish - action: publish:github - input: - allowedHosts: ['github.com'] - description: This is ${{ parameters.name }} - repoUrl: ${{ parameters.repoUrl }} - - # The final step is to register our new component in the catalog. - - id: register - name: Register - action: catalog:register - input: - repoContentsUrl: ${{ steps['publish'].output.repoContentsUrl }} - catalogInfoPath: '/catalog-info.yaml' - - # Outputs are displayed to the user after a successful execution of the template. - output: - links: - - title: Repository - url: ${{ steps['publish'].output.remoteUrl }} - - title: Open in catalog - icon: catalog - entityRef: ${{ steps['register'].output.entityRef }} diff --git a/workspaces/npm/mkdocs.yaml b/workspaces/npm/mkdocs.yaml new file mode 100644 index 0000000000..8ac37b0737 --- /dev/null +++ b/workspaces/npm/mkdocs.yaml @@ -0,0 +1,13 @@ +site_name: npm plugin for Backstage +site_description: A Backstage plugin that shows meta info and latest versions from a npm registry +repo_url: https://github.com/backstage/community-plugins +edit_uri: edit/main/workspaces/npm/docs + +plugins: + - techdocs-core + +nav: + - About: index.md + - Installation: install.md + - Usage: usage.md + - Registries: registries.md diff --git a/workspaces/npm/packages/app-next/knip-report.md b/workspaces/npm/packages/app-next/knip-report.md new file mode 100644 index 0000000000..d3589c972e --- /dev/null +++ b/workspaces/npm/packages/app-next/knip-report.md @@ -0,0 +1,34 @@ +# Knip report + +## Unused dependencies (19) + +| Name | Location | Severity | +| :------------------------------- | :----------- | :------- | +| @backstage/plugin-catalog-common | package.json | error | +| @backstage-community/plugin-npm | package.json | error | +| @backstage/plugin-catalog-graph | package.json | error | +| @backstage/plugin-catalog-react | package.json | error | +| @backstage/integration-react | package.json | error | +| @backstage/frontend-app-api | package.json | error | +| @backstage/core-compat-api | package.json | error | +| @backstage/core-components | package.json | error | +| @backstage/core-plugin-api | package.json | error | +| @backstage/plugin-api-docs | package.json | error | +| @backstage/catalog-model | package.json | error | +| @backstage/app-defaults | package.json | error | +| @backstage/core-app-api | package.json | error | +| @backstage/plugin-org | package.json | error | +| @material-ui/icons | package.json | error | +| @material-ui/core | package.json | error | +| styled-components | package.json | error | +| react-router-dom | package.json | error | +| react-use | package.json | error | + +## Unused devDependencies (4) + +| Name | Location | Severity | +| :-------------------------- | :----------- | :------- | +| @testing-library/user-event | package.json | error | +| @testing-library/react | package.json | error | +| @testing-library/dom | package.json | error | +| @playwright/test | package.json | error | diff --git a/workspaces/npm/packages/app/e2e-tests/app.test.ts b/workspaces/npm/packages/app/e2e-tests/app.test.ts index 839ff883de..c0d4c2eb16 100644 --- a/workspaces/npm/packages/app/e2e-tests/app.test.ts +++ b/workspaces/npm/packages/app/e2e-tests/app.test.ts @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Backstage Authors + * Copyright 2024 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/workspaces/npm/packages/backend/knip-report.md b/workspaces/npm/packages/backend/knip-report.md index 4b32479bad..aafbfad657 100644 --- a/workspaces/npm/packages/backend/knip-report.md +++ b/workspaces/npm/packages/backend/knip-report.md @@ -1,10 +1,11 @@ # Knip report -## Unused dependencies (11) +## Unused dependencies (12) | Name | Location | Severity | | :---------------------------------------------------- | :----------- | :------- | | @backstage/plugin-auth-backend-module-github-provider | package.json | error | +| @backstage-community/plugin-npm-backend | package.json | error | | @backstage/plugin-search-backend-node | package.json | error | | @backstage/plugin-permission-common | package.json | error | | @backstage/plugin-permission-node | package.json | error | diff --git a/workspaces/npm/packages/backend/package.json b/workspaces/npm/packages/backend/package.json index b64a38ce01..ca9930ff0b 100644 --- a/workspaces/npm/packages/backend/package.json +++ b/workspaces/npm/packages/backend/package.json @@ -21,6 +21,7 @@ "build-image": "docker build ../.. -f Dockerfile --tag backstage" }, "dependencies": { + "@backstage-community/plugin-npm-backend": "workspace:^", "@backstage/backend-defaults": "^0.6.2", "@backstage/config": "^1.3.1", "@backstage/plugin-app-backend": "^0.4.3", diff --git a/workspaces/npm/packages/backend/src/index.ts b/workspaces/npm/packages/backend/src/index.ts index b8f532f3ea..a9b9899984 100644 --- a/workspaces/npm/packages/backend/src/index.ts +++ b/workspaces/npm/packages/backend/src/index.ts @@ -56,4 +56,5 @@ backend.add(import('@backstage/plugin-search-backend-module-pg/alpha')); backend.add(import('@backstage/plugin-search-backend-module-catalog/alpha')); backend.add(import('@backstage/plugin-search-backend-module-techdocs/alpha')); +backend.add(import('@backstage-community/plugin-npm-backend')); backend.start(); diff --git a/workspaces/npm/plugins/npm-backend/.eslintrc.js b/workspaces/npm/plugins/npm-backend/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/workspaces/npm/plugins/npm-backend/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/workspaces/npm/plugins/npm-backend/README.md b/workspaces/npm/plugins/npm-backend/README.md new file mode 120000 index 0000000000..fe84005413 --- /dev/null +++ b/workspaces/npm/plugins/npm-backend/README.md @@ -0,0 +1 @@ +../../README.md \ No newline at end of file diff --git a/workspaces/npm/plugins/npm-backend/catalog-info.yaml b/workspaces/npm/plugins/npm-backend/catalog-info.yaml new file mode 100644 index 0000000000..f071950ee5 --- /dev/null +++ b/workspaces/npm/plugins/npm-backend/catalog-info.yaml @@ -0,0 +1,18 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-plugin-npm-backend + title: '@backstage-community/plugin-npm-backend' + description: A Backstage plugin that shows meta info and latest versions from a npm registry + annotations: + backstage.io/techdocs-entity: component:default/backstage-plugin-npm-workspace + npm/package: '@backstage-community/plugin-npm-backend' + links: + - url: https://github.com/backstage/community-plugins/tree/main/workspaces/npm/plugins/npm-backend + title: GitHub + icon: sourcecode +spec: + lifecycle: production + type: backstage-backend-plugin + owner: maintainers + subcomponentOf: backstage-plugin-npm diff --git a/workspaces/npm/plugins/npm-backend/config.d.ts b/workspaces/npm/plugins/npm-backend/config.d.ts new file mode 100644 index 0000000000..9a617aeed8 --- /dev/null +++ b/workspaces/npm/plugins/npm-backend/config.d.ts @@ -0,0 +1,43 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export interface Config { + npm?: { + /** + * Use another default registry. This automatically enforce usage of the backend. + * + * @visibility frontend + */ + defaultRegistry?: string; + /** + * List of registries that can be used to fetch packages from + */ + registries?: { + /** + * Registry name + */ + name?: string; + /** + * Registry base url + */ + url?: string; + /** + * Registry auth token + * @visibility secret + */ + token?: string; + }[]; + }; +} diff --git a/workspaces/npm/plugins/npm-backend/dev/index.ts b/workspaces/npm/plugins/npm-backend/dev/index.ts new file mode 100644 index 0000000000..fef47a9589 --- /dev/null +++ b/workspaces/npm/plugins/npm-backend/dev/index.ts @@ -0,0 +1,75 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { createBackend } from '@backstage/backend-defaults'; +import { mockServices } from '@backstage/backend-test-utils'; +import { catalogServiceMock } from '@backstage/plugin-catalog-node/testUtils'; + +// TEMPLATE NOTE: +// This is the development setup for your plugin that wires up a +// minimal backend that can use both real and mocked plugins and services. +// +// Start up the backend by running `yarn start` in the package directory. +// Once it's up and running, try out the following requests: +// +// Create a new todo item, standalone or for the sample component: +// +// curl http://localhost:7007/api/npm/todos -H 'Content-Type: application/json' -d '{"title": "My Todo"}' +// curl http://localhost:7007/api/npm/todos -H 'Content-Type: application/json' -d '{"title": "My Todo", "entityRef": "component:default/sample"}' +// +// List TODOs: +// +// curl http://localhost:7007/api/npm/todos +// +// Explicitly make an unauthenticated request, or with service auth: +// +// curl http://localhost:7007/api/npm/todos -H 'Authorization: Bearer mock-none-token' +// curl http://localhost:7007/api/npm/todos -H 'Authorization: Bearer mock-service-token' + +const backend = createBackend(); + +// TEMPLATE NOTE: +// Mocking the auth and httpAuth service allows you to call your plugin API without +// having to authenticate. +// +// If you want to use real auth, you can install the following instead: +// backend.add(import('@backstage/plugin-auth-backend')); +// backend.add(import('@backstage/plugin-auth-backend-module-guest-provider')); +backend.add(mockServices.auth.factory()); +backend.add(mockServices.httpAuth.factory()); + +// TEMPLATE NOTE: +// Rather than using a real catalog you can use a mock with a fixed set of entities. +backend.add( + catalogServiceMock.factory({ + entities: [ + { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'sample', + title: 'Sample Component', + }, + spec: { + type: 'service', + }, + }, + ], + }), +); + +backend.add(import('../src')); + +backend.start(); diff --git a/workspaces/npm/plugins/npm-backend/docs b/workspaces/npm/plugins/npm-backend/docs new file mode 120000 index 0000000000..92a7f82538 --- /dev/null +++ b/workspaces/npm/plugins/npm-backend/docs @@ -0,0 +1 @@ +../../docs \ No newline at end of file diff --git a/workspaces/npm/plugins/npm-backend/knip-report.md b/workspaces/npm/plugins/npm-backend/knip-report.md new file mode 100644 index 0000000000..e67e858ddf --- /dev/null +++ b/workspaces/npm/plugins/npm-backend/knip-report.md @@ -0,0 +1,15 @@ +# Knip report + +## Unused dependencies (2) + +| Name | Location | Severity | +| :------------------------------------- | :----------- | :------- | +| @backstage-community/plugin-npm-common | package.json | error | +| @backstage/catalog-client | package.json | error | + +## Unused devDependencies (2) + +| Name | Location | Severity | +| :--------------- | :----------- | :------- | +| @types/supertest | package.json | error | +| supertest | package.json | error | diff --git a/workspaces/npm/plugins/npm-backend/package.json b/workspaces/npm/plugins/npm-backend/package.json new file mode 100644 index 0000000000..44f4bb2f76 --- /dev/null +++ b/workspaces/npm/plugins/npm-backend/package.json @@ -0,0 +1,71 @@ +{ + "name": "@backstage-community/plugin-npm-backend", + "version": "1.1.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "backstage": { + "role": "backend-plugin", + "supported-versions": "1.28.0", + "pluginId": "npm", + "pluginPackage": "@backstage-community/plugin-npm-backend", + "pluginPackages": [ + "@backstage-community/plugin-npm", + "@backstage-community/plugin-npm-backend", + "@backstage-community/plugin-npm-common" + ] + }, + "scripts": { + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack" + }, + "dependencies": { + "@backstage-community/plugin-npm-common": "workspace:^", + "@backstage/backend-defaults": "^0.5.1", + "@backstage/backend-plugin-api": "^1.0.1", + "@backstage/catalog-client": "^1.7.1", + "@backstage/errors": "^1.2.4", + "@backstage/plugin-catalog-node": "^1.13.1", + "express": "^4.17.1", + "express-promise-router": "^4.1.0" + }, + "devDependencies": { + "@backstage/backend-test-utils": "^1.0.1", + "@backstage/cli": "^0.28.0", + "@types/express": "*", + "@types/supertest": "^2.0.12", + "supertest": "^6.2.4" + }, + "files": [ + "config.d.ts", + "dist" + ], + "configSchema": "config.d.ts", + "repository": { + "type": "git", + "url": "https://github.com/backstage/community-plugins", + "directory": "workspaces/npm/plugins/npm-backend" + }, + "keywords": [ + "backstage", + "plugin", + "npm" + ], + "homepage": "https://github.com/backstage/community-plugins/tree/main/workspaces/npm/plugins/npm-backend", + "bugs": "https://github.com/backstage/community-plugins/issues", + "maintainers": [ + "jerolimov", + "karthikjeeyar" + ], + "author": "Christoph Jerolimov" +} diff --git a/workspaces/npm/plugins/npm-backend/report.api.md b/workspaces/npm/plugins/npm-backend/report.api.md new file mode 100644 index 0000000000..c5a1472325 --- /dev/null +++ b/workspaces/npm/plugins/npm-backend/report.api.md @@ -0,0 +1,13 @@ +## API Report File for "@backstage-community/plugin-npm-backend" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; + +// @public +const npmPlugin: BackendFeature; +export default npmPlugin; + +// (No @packageDocumentation comment for this package) +``` diff --git a/workspaces/npm/plugins/npm-backend/src/index.ts b/workspaces/npm/plugins/npm-backend/src/index.ts new file mode 100644 index 0000000000..152f6579df --- /dev/null +++ b/workspaces/npm/plugins/npm-backend/src/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export { npmPlugin as default } from './plugin'; diff --git a/workspaces/npm/plugins/npm-backend/src/plugin.ts b/workspaces/npm/plugins/npm-backend/src/plugin.ts new file mode 100644 index 0000000000..eb0655cfc0 --- /dev/null +++ b/workspaces/npm/plugins/npm-backend/src/plugin.ts @@ -0,0 +1,59 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { + coreServices, + createBackendPlugin, +} from '@backstage/backend-plugin-api'; +import { catalogServiceRef } from '@backstage/plugin-catalog-node/alpha'; + +import { createRouter } from './router'; +import { NpmRegistryServiceImpl } from './services/NpmRegistryServiceImpl'; + +/** + * npmPlugin backend plugin + * + * @public + */ +export const npmPlugin = createBackendPlugin({ + pluginId: 'npm', + register(env) { + env.registerInit({ + deps: { + logger: coreServices.logger, + auth: coreServices.auth, + config: coreServices.rootConfig, + httpAuth: coreServices.httpAuth, + httpRouter: coreServices.httpRouter, + catalog: catalogServiceRef, + }, + async init({ logger, auth, config, httpAuth, httpRouter, catalog }) { + const npmRegistryService = new NpmRegistryServiceImpl({ + logger, + auth, + config, + catalog, + }); + + httpRouter.use( + await createRouter({ + httpAuth, + npmRegistryService, + }), + ); + }, + }); + }, +}); diff --git a/workspaces/npm/plugins/npm-backend/src/router.ts b/workspaces/npm/plugins/npm-backend/src/router.ts new file mode 100644 index 0000000000..96161546f4 --- /dev/null +++ b/workspaces/npm/plugins/npm-backend/src/router.ts @@ -0,0 +1,50 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { HttpAuthService } from '@backstage/backend-plugin-api'; +import { ResponseError } from '@backstage/errors'; +import express from 'express'; +import Router from 'express-promise-router'; +import { NpmRegistryService } from './services'; + +export async function createRouter({ + httpAuth, + npmRegistryService, +}: { + httpAuth: HttpAuthService; + npmRegistryService: NpmRegistryService; +}): Promise<express.Router> { + const router = Router(); + router.use(express.json()); + + router.get('/:entityRef/package-info', async (req, res) => { + const entityRef = req.params.entityRef; + const credentials = await httpAuth.credentials(req, { allow: ['user'] }); + try { + const packageInfo = await npmRegistryService.getPackageInfo(entityRef, { + credentials, + }); + res.json(packageInfo); + } catch (error) { + if (error instanceof ResponseError) { + res.status(error.statusCode).json(error.response); + } else { + throw error; + } + } + }); + + return router; +} diff --git a/workspaces/npm/plugins/npm-backend/src/services/NpmRegistryService.ts b/workspaces/npm/plugins/npm-backend/src/services/NpmRegistryService.ts new file mode 100644 index 0000000000..efc274cda4 --- /dev/null +++ b/workspaces/npm/plugins/npm-backend/src/services/NpmRegistryService.ts @@ -0,0 +1,30 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { + BackstageCredentials, + BackstageUserPrincipal, +} from '@backstage/backend-plugin-api'; + +import { NpmRegistryPackageInfo } from '@backstage-community/plugin-npm-common'; + +export interface NpmRegistryService { + getPackageInfo( + entityRef: string, + options: { + credentials: BackstageCredentials<BackstageUserPrincipal>; + }, + ): Promise<NpmRegistryPackageInfo>; +} diff --git a/workspaces/npm/plugins/npm-backend/src/services/NpmRegistryServiceImpl.ts b/workspaces/npm/plugins/npm-backend/src/services/NpmRegistryServiceImpl.ts new file mode 100644 index 0000000000..cbb6f08ec1 --- /dev/null +++ b/workspaces/npm/plugins/npm-backend/src/services/NpmRegistryServiceImpl.ts @@ -0,0 +1,107 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { + AuthService, + BackstageCredentials, + BackstageUserPrincipal, + LoggerService, + RootConfigService, +} from '@backstage/backend-plugin-api'; +import { NotFoundError } from '@backstage/errors'; +import { catalogServiceRef } from '@backstage/plugin-catalog-node/alpha'; + +import { + NpmAnnotation, + NpmRegistryClient, + NpmRegistryPackageInfo, +} from '@backstage-community/plugin-npm-common'; + +import { NpmRegistryService } from './NpmRegistryService'; +import { Config } from '../../config'; + +export type Options = { + logger: LoggerService; + auth: AuthService; + config: RootConfigService; + // TODO update CatalogService + catalog: typeof catalogServiceRef.T; +}; + +export class NpmRegistryServiceImpl implements NpmRegistryService { + private readonly logger: LoggerService; + private readonly auth: AuthService; + private readonly config: RootConfigService; + private readonly catalog: typeof catalogServiceRef.T; + + constructor(options: Options) { + this.logger = options.logger; + this.auth = options.auth; + this.config = options.config; + this.catalog = options.catalog; + } + + async getPackageInfo( + entityRef: string, + options: { credentials: BackstageCredentials<BackstageUserPrincipal> }, + ): Promise<NpmRegistryPackageInfo> { + const { token } = await this.auth.getPluginRequestToken({ + onBehalfOf: options.credentials, + targetPluginId: 'catalog', + }); + const entity = await this.catalog.getEntityByRef(entityRef, { + token, + }); + if (!entity) { + throw new NotFoundError(`No entity found for ref '${entityRef}'`); + } + + const config = this.config.getOptional<Config['npm']>('npm'); + const defaultRegistry = config?.defaultRegistry; + + const packageName = + entity.metadata.annotations?.[NpmAnnotation.PACKAGE_NAME]; + const registryName = + entity.metadata.annotations?.[NpmAnnotation.REGISTRY_NAME] || + defaultRegistry; + if (!packageName) { + throw new NotFoundError( + `Npm package name not defined at entity '${entityRef}'`, + ); + } + + const registry = config?.registries?.find(r => r.name === registryName); + if (!registry && registryName !== 'default' && registryName !== 'npmjs') { + throw new NotFoundError( + `Npm registry config '${registryName}' not found as defined in entity '${entityRef}'`, + ); + } + + this.logger.info('Will use npmjs package info:', { + entityRef, + packageName, + registryUrl: registry?.url, + registryToken: registry?.token ? 'yes' : 'no', + }); + + const client = new NpmRegistryClient({ + // TODO pass apiFetch.fetch + baseUrl: registry?.url, + token: registry?.token, + }); + const packageInfo = await client.getPackageInfo(packageName); + return packageInfo; + } +} diff --git a/workspaces/npm/plugins/npm-backend/src/services/index.ts b/workspaces/npm/plugins/npm-backend/src/services/index.ts new file mode 100644 index 0000000000..d5b8520582 --- /dev/null +++ b/workspaces/npm/plugins/npm-backend/src/services/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export * from './NpmRegistryService'; +export * from './NpmRegistryServiceImpl'; diff --git a/workspaces/npm/examples/template/content/index.js b/workspaces/npm/plugins/npm-backend/src/setupTests.ts similarity index 92% rename from workspaces/npm/examples/template/content/index.js rename to workspaces/npm/plugins/npm-backend/src/setupTests.ts index 29cca731de..c7ce5c0988 100644 --- a/workspaces/npm/examples/template/content/index.js +++ b/workspaces/npm/plugins/npm-backend/src/setupTests.ts @@ -13,4 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -console.log('Hello from ${{ values.name }}!'); +export {}; diff --git a/workspaces/npm/plugins/npm-common/.eslintrc.js b/workspaces/npm/plugins/npm-common/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/workspaces/npm/plugins/npm-common/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/workspaces/npm/plugins/npm-common/README.md b/workspaces/npm/plugins/npm-common/README.md new file mode 120000 index 0000000000..fe84005413 --- /dev/null +++ b/workspaces/npm/plugins/npm-common/README.md @@ -0,0 +1 @@ +../../README.md \ No newline at end of file diff --git a/workspaces/npm/plugins/npm-common/catalog-info.yaml b/workspaces/npm/plugins/npm-common/catalog-info.yaml new file mode 100644 index 0000000000..3a5d296460 --- /dev/null +++ b/workspaces/npm/plugins/npm-common/catalog-info.yaml @@ -0,0 +1,18 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-plugin-npm-common + title: '@backstage-community/plugin-npm-common' + description: A Backstage plugin that shows meta info and latest versions from a npm registry + annotations: + backstage.io/techdocs-entity: component:default/backstage-plugin-npm-workspace + npm/package: '@backstage-community/plugin-npm-common' + links: + - url: https://github.com/backstage/community-plugins/tree/main/workspaces/npm/plugins/npm-common + title: GitHub + icon: sourcecode +spec: + lifecycle: production + type: backstage-common-library + owner: maintainers + subcomponentOf: backstage-plugin-npm diff --git a/workspaces/npm/plugins/npm-common/docs b/workspaces/npm/plugins/npm-common/docs new file mode 120000 index 0000000000..92a7f82538 --- /dev/null +++ b/workspaces/npm/plugins/npm-common/docs @@ -0,0 +1 @@ +../../docs \ No newline at end of file diff --git a/workspaces/npm/plugins/npm-common/knip-report.md b/workspaces/npm/plugins/npm-common/knip-report.md new file mode 100644 index 0000000000..28921c328d --- /dev/null +++ b/workspaces/npm/plugins/npm-common/knip-report.md @@ -0,0 +1 @@ +# Knip report diff --git a/workspaces/npm/plugins/npm-common/package.json b/workspaces/npm/plugins/npm-common/package.json new file mode 100644 index 0000000000..6ce0ee2053 --- /dev/null +++ b/workspaces/npm/plugins/npm-common/package.json @@ -0,0 +1,47 @@ +{ + "name": "@backstage-community/plugin-npm-common", + "description": "Common functionalities for the npm plugin", + "version": "1.1.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "module": "dist/index.esm.js", + "types": "dist/index.d.ts" + }, + "repository": { + "type": "git", + "url": "https://github.com/backstage/community-plugins", + "directory": "workspaces/npm/plugins/npm-common" + }, + "backstage": { + "role": "common-library", + "pluginId": "npm", + "pluginPackages": [ + "@backstage-community/plugin-npm", + "@backstage-community/plugin-npm-backend", + "@backstage-community/plugin-npm-common" + ] + }, + "sideEffects": false, + "scripts": { + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack" + }, + "dependencies": { + "@backstage/catalog-model": "^1.7.0", + "@backstage/errors": "^1.2.4" + }, + "devDependencies": { + "@backstage/cli": "^0.28.0" + }, + "files": [ + "dist" + ] +} diff --git a/workspaces/npm/plugins/npm-common/report.api.md b/workspaces/npm/plugins/npm-common/report.api.md new file mode 100644 index 0000000000..2b5b4278ff --- /dev/null +++ b/workspaces/npm/plugins/npm-common/report.api.md @@ -0,0 +1,104 @@ +## API Report File for "@backstage-community/plugin-npm-common" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { Entity } from '@backstage/catalog-model'; + +// @public +export const isNpmAvailable: (entity: Entity) => boolean; + +// @public (undocumented) +export enum NpmAnnotation { + // (undocumented) + PACKAGE_NAME = 'npm/package', + // (undocumented) + REGISTRY_NAME = 'npm/registry', + // (undocumented) + SHOW_TAGS = 'npm/show-tags', + // (undocumented) + STABLE_TAG = 'npm/stable-tag', +} + +// @public (undocumented) +export class NpmRegistryClient { + constructor(options: { + fetch?: typeof fetch; + baseUrl?: string; + token?: string; + }); + // (undocumented) + getPackageInfo(packageName: string): Promise<NpmRegistryPackageInfo>; +} + +// @public +export interface NpmRegistryPackageInfo { + // (undocumented) + 'dist-tags': { + [tag: string]: string; + }; + // (undocumented) + _attachments?: { + [filename: string]: { + content_type: string; + data: string; + }; + }; + // (undocumented) + author?: + | { + name: string; + email: string; + url: string; + } + | string; + // (undocumented) + bugs?: { + url?: string; + }; + // (undocumented) + description?: string; + // (undocumented) + homepage?: string; + // (undocumented) + _id: string; + // (undocumented) + keywords?: string[]; + // (undocumented) + license?: string; + // (undocumented) + name: string; + // (undocumented) + readme?: string; + // (undocumented) + repository?: { + type: string; + url: string; + directory?: string; + }; + // (undocumented) + _rev: string; + // (undocumented) + time?: { + created: string; + modified: string; + [version: string]: string; + }; + // (undocumented) + versions: { + [version: string]: NpmRegistryPackageInfoVersion; + }; +} + +// @public +export interface NpmRegistryPackageInfoVersion { + // (undocumented) + description: string; + // (undocumented) + homepage: string; + // (undocumented) + name: string; + // (undocumented) + version: string; +} +``` diff --git a/workspaces/npm/plugins/npm-common/src/NpmRegistryClient.ts b/workspaces/npm/plugins/npm-common/src/NpmRegistryClient.ts new file mode 100644 index 0000000000..432babb64d --- /dev/null +++ b/workspaces/npm/plugins/npm-common/src/NpmRegistryClient.ts @@ -0,0 +1,54 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { ResponseError } from '@backstage/errors'; + +import { NpmRegistryPackageInfo } from './types'; + +/** + * @public + */ +export class NpmRegistryClient { + private readonly fetch: typeof fetch; + private readonly baseUrl: string; + private readonly token?: string; + + constructor(options: { + fetch?: typeof fetch; + baseUrl?: string; + token?: string; + }) { + this.fetch = options?.fetch || global.fetch.bind(global); + this.baseUrl = options.baseUrl || 'https://registry.npmjs.com'; + this.token = options.token; + } + + async getPackageInfo(packageName: string): Promise<NpmRegistryPackageInfo> { + if (!packageName) { + throw new Error('No package name provided'); + } + + const url = `${this.baseUrl}/${encodeURIComponent(packageName)}`; + + const response = await this.fetch(url, { + headers: this.token ? { Authorization: this.token } : undefined, + }); + + if (!response.ok) { + throw await ResponseError.fromResponse(response); + } + return response.json(); + } +} diff --git a/workspaces/npm/plugins/npm/src/annotations.ts b/workspaces/npm/plugins/npm-common/src/annotations.ts similarity index 77% rename from workspaces/npm/plugins/npm/src/annotations.ts rename to workspaces/npm/plugins/npm-common/src/annotations.ts index c771885f05..f6f6665d74 100644 --- a/workspaces/npm/plugins/npm/src/annotations.ts +++ b/workspaces/npm/plugins/npm-common/src/annotations.ts @@ -14,8 +14,12 @@ * limitations under the License. */ -export const NPM_PACKAGE_ANNOTATION = 'npm/package'; - -export const NPM_STABLE_TAG_ANNOTATION = 'npm/stable-tag'; - -export const NPM_SHOW_TAGS_ANNOTATION = 'npm/show-tags'; +/** + * @public + */ +export enum NpmAnnotation { + PACKAGE_NAME = 'npm/package', + REGISTRY_NAME = 'npm/registry', + STABLE_TAG = 'npm/stable-tag', + SHOW_TAGS = 'npm/show-tags', +} diff --git a/workspaces/npm/plugins/npm-common/src/index.ts b/workspaces/npm/plugins/npm-common/src/index.ts new file mode 100644 index 0000000000..91e679cfc9 --- /dev/null +++ b/workspaces/npm/plugins/npm-common/src/index.ts @@ -0,0 +1,26 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Common functionalities for the npm plugin. + * + * @packageDocumentation + */ + +export * from './annotations'; +export * from './NpmRegistryClient'; +export * from './types'; +export * from './utils'; diff --git a/workspaces/npm/plugins/npm-common/src/setupTests.ts b/workspaces/npm/plugins/npm-common/src/setupTests.ts new file mode 100644 index 0000000000..c7ce5c0988 --- /dev/null +++ b/workspaces/npm/plugins/npm-common/src/setupTests.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export {}; diff --git a/workspaces/npm/plugins/npm/src/api.ts b/workspaces/npm/plugins/npm-common/src/types.ts similarity index 58% rename from workspaces/npm/plugins/npm/src/api.ts rename to workspaces/npm/plugins/npm-common/src/types.ts index f88f15ec1f..d8781f474f 100644 --- a/workspaces/npm/plugins/npm/src/api.ts +++ b/workspaces/npm/plugins/npm-common/src/types.ts @@ -14,16 +14,24 @@ * limitations under the License. */ -// From https://github.com/npm/registry/blob/main/docs/REGISTRY-API.md -export interface NpmRegistryVersion { +/** + * NPM package info `versions` type definition based on https://github.com/npm/registry/blob/main/docs/REGISTRY-API.md + * + * @public + */ +export interface NpmRegistryPackageInfoVersion { name: string; version: string; homepage: string; description: string; } -// From https://github.com/npm/registry/blob/main/docs/REGISTRY-API.md -export interface NpmRegistryPackage { +/** + * NPM registry package info type definition based on https://github.com/npm/registry/blob/main/docs/REGISTRY-API.md + * + * @public + */ +export interface NpmRegistryPackageInfo { _id: string; _rev: string; name: string; @@ -34,9 +42,10 @@ export interface NpmRegistryPackage { [tag: string]: string; }; versions: { - [version: string]: NpmRegistryVersion; + [version: string]: NpmRegistryPackageInfoVersion; }; - time: { + // Available on npmjs and GitHub, not available on GitLab + time?: { created: string; modified: string; [version: string]: string; @@ -65,28 +74,3 @@ export interface NpmRegistryPackage { }; readme?: string; } - -const fetchNpmPackage = async (packageName: string | undefined) => { - if (!packageName) { - throw new Error('No package name provided'); - } - const response = await fetch( - `https://registry.npmjs.org/${encodeURIComponent(packageName)}`, - ); - if (response.status === 404) { - throw new Error( - `Package ${packageName} not found (private repositories are not supported yet)`, - ); - } - if (!response.ok) { - throw new Error( - `Failed to fetch info for package ${packageName}: ${response.status} ${response.statusText}`, - ); - } - const json = await response.json(); - return json as NpmRegistryPackage; -}; - -export const API = { - fetchNpmPackage, -}; diff --git a/workspaces/npm/plugins/npm/src/utils/isNpmAvailable.ts b/workspaces/npm/plugins/npm-common/src/utils.ts similarity index 86% rename from workspaces/npm/plugins/npm/src/utils/isNpmAvailable.ts rename to workspaces/npm/plugins/npm-common/src/utils.ts index 7839280ddb..b450c22637 100644 --- a/workspaces/npm/plugins/npm/src/utils/isNpmAvailable.ts +++ b/workspaces/npm/plugins/npm-common/src/utils.ts @@ -15,7 +15,7 @@ */ import { type Entity } from '@backstage/catalog-model'; -import { NPM_PACKAGE_ANNOTATION } from '../annotations'; +import { NpmAnnotation } from './annotations'; /** * Function that returns true if the given entity contains at least one @@ -24,5 +24,5 @@ import { NPM_PACKAGE_ANNOTATION } from '../annotations'; * @public */ export const isNpmAvailable = (entity: Entity): boolean => { - return Boolean(entity.metadata.annotations?.[NPM_PACKAGE_ANNOTATION]); + return Boolean(entity.metadata.annotations?.[NpmAnnotation.PACKAGE_NAME]); }; diff --git a/workspaces/npm/plugins/npm/README.md b/workspaces/npm/plugins/npm/README.md deleted file mode 100644 index 0baf1de690..0000000000 --- a/workspaces/npm/plugins/npm/README.md +++ /dev/null @@ -1,145 +0,0 @@ -# npm plugin for Backstage - -A Backstage plugin that shows information and latest releases/versions from a npm registry -for catalog entities. - -## Screenshots - -### Npm info card - -![Screenshot](docs/npm-info-card.png) - -### Npm release overview card - -![Screenshot](docs/npm-release-overview-card.png) - -### Extended catalog entity overview tab (example) - -![Screenshot](docs/catalog-entity-overview-tab.png) - -### New catalog entity npm release tab - -![Screenshot](docs/catalog-entity-npm-release-tab.png) - -## For users - -### Enable npm cards for a catalog entity - -To enable the different npm cards you must add the `npm/package` annotation -with the name of the npm package: - -```yaml -apiVersion: backstage.io/v1alpha1 -kind: Component -metadata: - name: react - annotations: - npm/package: react -``` - -The "npm info" card shows the information of the latest 'stable' npm release -and use the common `latest` tag by default. This could be changed with `npm/stable-tag`: - -```yaml -apiVersion: backstage.io/v1alpha1 -kind: Component -metadata: - name: react - annotations: - npm/package: react - npm/stable-tag: latest, stable, next, etc. -``` - -## For administrators - -### Install frontend and manual integrate into catalog - -1. Install the frontend plugin: - - ```sh - yarn workspace app add @backstage-community/plugin-npm - ``` - -2. Add cards based on your needs to `packages/app/src/components/catalog/EntityPage.tsx`: - - After all other imports: - - ```tsx - import { - isNpmAvailable, - EntityNpmInfoCard, - EntityNpmReleaseOverviewCard, - EntityNpmReleaseTableCard, - } from '@backstage-community/plugin-npm'; - ``` - -3. Add to `const overviewContent` after `EntityAboutCard`: - - ```tsx - <EntitySwitch> - <EntitySwitch.Case if={isNpmAvailable}> - <Grid container item md={6} xs={12}> - <Grid item md={12}> - <EntityNpmInfoCard /> - </Grid> - <Grid item md={12}> - <EntityNpmReleaseOverviewCard /> - </Grid> - </Grid> - </EntitySwitch.Case> - </EntitySwitch> - ``` - -4. Add to `const serviceEntityPage` and `const websiteEntityPage` after the `/ci-cd` case - and to `const defaultEntityPage` between the `/` and `/docs` routecase. - - ```tsx - <EntityLayout.Route - if={isNpmAvailable} - path="/npm-releases" - title="NPM Releases" - > - <EntityNpmReleaseTableCard /> - </EntityLayout.Route> - ``` - -### Use new frontend system - -1. Install the frontend plugin: - - ```sh - yarn workspace app add @backstage-community/plugin-npm - ``` - -2. Enable the plugin in your `packages/app(-next)/src/App.tsx`: - - After all other imports: - - ```tsx - import npmPlugin from '@backstage-community/plugin-npm/alpha'; - ``` - - ```tsx - export const app = createApp({ - features: [ - catalogPlugin, - catalogImportPlugin, - userSettingsPlugin, - npmPlugin, - // ... - ], - }); - ``` - -### Test catalog entities - -For testing purpose you can import this catalog entities: - -```yaml -catalog: - locations: - - type: url - target: https://github.com/backstage/community-plugins/blob/main/workspaces/npm/examples/entities.yaml - rules: - - allow: [System, Component] -``` diff --git a/workspaces/npm/plugins/npm/README.md b/workspaces/npm/plugins/npm/README.md new file mode 120000 index 0000000000..fe84005413 --- /dev/null +++ b/workspaces/npm/plugins/npm/README.md @@ -0,0 +1 @@ +../../README.md \ No newline at end of file diff --git a/workspaces/npm/plugins/npm/catalog-info.yaml b/workspaces/npm/plugins/npm/catalog-info.yaml index b3de13d432..2c0b185e14 100644 --- a/workspaces/npm/plugins/npm/catalog-info.yaml +++ b/workspaces/npm/plugins/npm/catalog-info.yaml @@ -1,10 +1,18 @@ apiVersion: backstage.io/v1alpha1 kind: Component metadata: - name: backstage-plugin-npm + name: backstage-plugin-npm-frontend title: '@backstage-community/plugin-npm' description: A Backstage plugin that shows meta info and latest versions from a npm registry + annotations: + backstage.io/techdocs-entity: component:default/backstage-plugin-npm-workspace + npm/package: '@backstage-community/plugin-npm' + links: + - url: https://github.com/backstage/community-plugins/tree/main/workspaces/npm/plugins/npm + title: GitHub + icon: sourcecode spec: - lifecycle: experimental + lifecycle: production type: backstage-frontend-plugin owner: maintainers + subcomponentOf: backstage-plugin-npm diff --git a/workspaces/npm/plugins/npm/config.d.ts b/workspaces/npm/plugins/npm/config.d.ts new file mode 100644 index 0000000000..8977e458ad --- /dev/null +++ b/workspaces/npm/plugins/npm/config.d.ts @@ -0,0 +1,25 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export interface Config { + npm?: { + /** + * Use another default registry. This automatically enforce usage of the backend. + * + * @visibility frontend + */ + defaultRegistry?: string; + }; +} diff --git a/workspaces/npm/plugins/npm/docs b/workspaces/npm/plugins/npm/docs new file mode 120000 index 0000000000..92a7f82538 --- /dev/null +++ b/workspaces/npm/plugins/npm/docs @@ -0,0 +1 @@ +../../docs \ No newline at end of file diff --git a/workspaces/npm/plugins/npm/knip-report.md b/workspaces/npm/plugins/npm/knip-report.md index 703b798295..32a9e34e05 100644 --- a/workspaces/npm/plugins/npm/knip-report.md +++ b/workspaces/npm/plugins/npm/knip-report.md @@ -1,5 +1,11 @@ # Knip report +## Unused dependencies (1) + +| Name | Location | Severity | +| :------------------------------------- | :----------- | :------- | +| @backstage-community/plugin-npm-common | package.json | error | + ## Unused devDependencies (3) | Name | Location | Severity | @@ -7,3 +13,10 @@ | @testing-library/user-event | package.json | error | | @testing-library/react | package.json | error | | @backstage/test-utils | package.json | error | + +## Unlisted dependencies (2) + +| Name | Location | Severity | +| :----------------------------- | :-------------------------- | :------- | +| @backstage/errors | src/hooks/usePackageInfo.ts | error | +| @backstage/frontend-plugin-api | src/alpha.tsx | error | diff --git a/workspaces/npm/plugins/npm/package.json b/workspaces/npm/plugins/npm/package.json index 133613a8f0..1a5dcbe613 100644 --- a/workspaces/npm/plugins/npm/package.json +++ b/workspaces/npm/plugins/npm/package.json @@ -14,7 +14,9 @@ "pluginId": "npm", "pluginPackage": "@backstage-community/plugin-npm", "pluginPackages": [ - "@backstage-community/plugin-npm" + "@backstage-community/plugin-npm", + "@backstage-community/plugin-npm-backend", + "@backstage-community/plugin-npm-common" ] }, "exports": { @@ -43,9 +45,12 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { + "@backstage-community/plugin-npm-common": "workspace:^", "@backstage/catalog-model": "^1.7.2", "@backstage/core-components": "^0.16.2", "@backstage/core-plugin-api": "^1.10.2", + "@backstage/errors": "^1.2.4", + "@backstage/frontend-plugin-api": "^0.9.3", "@backstage/plugin-catalog-react": "^1.15.0", "@backstage/theme": "^0.6.3", "@material-ui/core": "^4.9.13", @@ -65,8 +70,10 @@ "react": "^16.13.1 || ^17.0.0 || ^18.0.0" }, "files": [ + "config.d.ts", "dist" ], + "configSchema": "config.d.ts", "repository": { "type": "git", "url": "https://github.com/backstage/community-plugins", diff --git a/workspaces/npm/plugins/npm/report-alpha.api.md b/workspaces/npm/plugins/npm/report-alpha.api.md index b16eb9a101..dd3895ce3f 100644 --- a/workspaces/npm/plugins/npm/report-alpha.api.md +++ b/workspaces/npm/plugins/npm/report-alpha.api.md @@ -4,6 +4,7 @@ ```ts import { FrontendPlugin } from '@backstage/frontend-plugin-api'; +import { isNpmAvailable } from '@backstage-community/plugin-npm-common'; // @alpha const _default: FrontendPlugin<{}, {}, {}>; @@ -18,5 +19,7 @@ export const entityNpmReleaseOverviewCard: any; // @alpha export const entityNpmReleaseTableCard: any; +export { isNpmAvailable }; + // (No @packageDocumentation comment for this package) ``` diff --git a/workspaces/npm/plugins/npm/report.api.md b/workspaces/npm/plugins/npm/report.api.md index 05e3c31fb6..1454c0eb07 100644 --- a/workspaces/npm/plugins/npm/report.api.md +++ b/workspaces/npm/plugins/npm/report.api.md @@ -6,7 +6,7 @@ /// <reference types="react" /> import { BackstagePlugin } from '@backstage/core-plugin-api'; -import { Entity } from '@backstage/catalog-model'; +import { isNpmAvailable } from '@backstage-community/plugin-npm-common'; import { JSX as JSX_2 } from 'react'; import { RouteRef } from '@backstage/core-plugin-api'; @@ -19,8 +19,7 @@ export const EntityNpmReleaseOverviewCard: () => JSX_2.Element; // @public export const EntityNpmReleaseTableCard: () => JSX_2.Element; -// @public -export const isNpmAvailable: (entity: Entity) => boolean; +export { isNpmAvailable }; // @public @deprecated (undocumented) export const NpmInfoCard: () => JSX_2.Element; diff --git a/workspaces/npm/plugins/npm/src/alpha.tsx b/workspaces/npm/plugins/npm/src/alpha.tsx index 0db40b7a46..c8eecdb5b6 100644 --- a/workspaces/npm/plugins/npm/src/alpha.tsx +++ b/workspaces/npm/plugins/npm/src/alpha.tsx @@ -20,7 +20,9 @@ import { EntityContentBlueprint, } from '@backstage/plugin-catalog-react/alpha'; -import { isNpmAvailable } from './utils/isNpmAvailable'; +import { isNpmAvailable } from '@backstage-community/plugin-npm-common'; + +export { isNpmAvailable } from '@backstage-community/plugin-npm-common'; /** * Card for the catalog (entity page) that shows the npm diff --git a/workspaces/npm/plugins/npm/src/api/NpmBackendApi.ts b/workspaces/npm/plugins/npm/src/api/NpmBackendApi.ts new file mode 100644 index 0000000000..caa235f999 --- /dev/null +++ b/workspaces/npm/plugins/npm/src/api/NpmBackendApi.ts @@ -0,0 +1,23 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { NpmRegistryPackageInfo } from '@backstage-community/plugin-npm-common'; + +/** + * @public + */ +export interface NpmBackendApi { + getPackageInfo(entityRef: string): Promise<NpmRegistryPackageInfo>; +} diff --git a/workspaces/npm/plugins/npm/src/api/NpmBackendClient.ts b/workspaces/npm/plugins/npm/src/api/NpmBackendClient.ts new file mode 100644 index 0000000000..234ee1ea13 --- /dev/null +++ b/workspaces/npm/plugins/npm/src/api/NpmBackendClient.ts @@ -0,0 +1,49 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { DiscoveryApi, FetchApi } from '@backstage/core-plugin-api'; +import { NpmRegistryPackageInfo } from '@backstage-community/plugin-npm-common'; + +import { NpmBackendApi } from './NpmBackendApi'; + +export type Options = { + discoveryApi: DiscoveryApi; + fetchApi: FetchApi; +}; + +export class NpmBackendClient implements NpmBackendApi { + private readonly discoveryApi: DiscoveryApi; + private readonly fetchApi: FetchApi; + + constructor(options: Options) { + this.discoveryApi = options.discoveryApi; + this.fetchApi = options.fetchApi; + } + + async getPackageInfo(entityRef: string): Promise<NpmRegistryPackageInfo> { + const baseUrl = await this.discoveryApi.getBaseUrl('npm'); + const url = `${baseUrl}/${encodeURIComponent(entityRef)}/package-info`; + + const response = await this.fetchApi.fetch(url); + if (!response.ok) { + throw new Error( + `Unexpected status code: ${response.status} ${response.statusText}`, + ); + } + + const data = await response.json(); + return data as NpmRegistryPackageInfo; + } +} diff --git a/workspaces/npm/plugins/npm/src/api/index.ts b/workspaces/npm/plugins/npm/src/api/index.ts new file mode 100644 index 0000000000..7fab9b4c6e --- /dev/null +++ b/workspaces/npm/plugins/npm/src/api/index.ts @@ -0,0 +1,24 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { createApiRef } from '@backstage/core-plugin-api'; + +import { NpmBackendApi } from './NpmBackendApi'; + +export * from './NpmBackendClient'; + +export const NpmBackendApiRef = createApiRef<NpmBackendApi>({ + id: 'plugin.npm.backend-api-ref', +}); diff --git a/workspaces/npm/plugins/npm/src/components/EntityNpmInfoCard.tsx b/workspaces/npm/plugins/npm/src/components/EntityNpmInfoCard.tsx index f6f0b8bd73..cbf2d15b3e 100644 --- a/workspaces/npm/plugins/npm/src/components/EntityNpmInfoCard.tsx +++ b/workspaces/npm/plugins/npm/src/components/EntityNpmInfoCard.tsx @@ -14,23 +14,24 @@ * limitations under the License. */ import React from 'react'; + import { ErrorPanel, InfoCard } from '@backstage/core-components'; +import { + MissingAnnotationEmptyState, + useEntity, +} from '@backstage/plugin-catalog-react'; + +import { NpmAnnotation } from '@backstage-community/plugin-npm-common'; + import Box from '@material-ui/core/Box'; import CircularProgress from '@material-ui/core/CircularProgress'; import Grid, { GridSize } from '@material-ui/core/Grid'; import Typography from '@material-ui/core/Typography'; import { makeStyles } from '@material-ui/core/styles'; -import { - MissingAnnotationEmptyState, - useEntity, -} from '@backstage/plugin-catalog-react'; -import useAsync from 'react-use/esm/useAsync'; + import { DateTime } from 'luxon'; -import { - NPM_PACKAGE_ANNOTATION, - NPM_STABLE_TAG_ANNOTATION, -} from '../annotations'; -import { API } from '../api'; + +import { usePackageInfo } from '../hooks/usePackageInfo'; // From https://github.com/backstage/backstage/blob/master/plugins/catalog/src/components/AboutCard/AboutField.tsx const useStyles = makeStyles(theme => ({ @@ -82,34 +83,33 @@ function GridItem({ */ export const EntityNpmInfoCard = () => { const { entity } = useEntity(); + const { packageInfo, loading, error } = usePackageInfo(); - const packageName = entity.metadata.annotations?.[NPM_PACKAGE_ANNOTATION]; - - const { - value: packageInfo, - loading, - error, - } = useAsync(() => API.fetchNpmPackage(packageName), [packageName]); + const packageName = entity.metadata.annotations?.[NpmAnnotation.PACKAGE_NAME]; if (!packageName) { return ( <MissingAnnotationEmptyState - annotation={NPM_PACKAGE_ANNOTATION} + annotation={NpmAnnotation.PACKAGE_NAME} readMoreUrl="https://backstage.io/docs/features/software-catalog/descriptor-format" /> ); } const latestTag = - entity.metadata.annotations?.[NPM_STABLE_TAG_ANNOTATION] ?? 'latest'; + entity.metadata.annotations?.[NpmAnnotation.STABLE_TAG] ?? 'latest'; const latestVersion = packageInfo?.['dist-tags']?.[latestTag]; const latestPublishedAt = latestVersion ? packageInfo?.time?.[latestVersion] : undefined; - const npmLink = packageInfo - ? `https://www.npmjs.com/package/${packageName}` - : null; + const registryName = + entity.metadata.annotations?.[NpmAnnotation.REGISTRY_NAME]; + + const npmLink = + packageInfo && !registryName + ? `https://www.npmjs.com/package/${packageName}` + : null; let repositoryLink: string | undefined; if (packageInfo?.repository?.url) { @@ -189,6 +189,10 @@ export const EntityNpmInfoCard = () => { <GridItem label="Keywords" value={packageInfo.keywords.join(', ')} /> ) : null} + {registryName ? ( + <GridItem label="Registry name" value={registryName} /> + ) : null} + {npmLink ? ( <GridItem label="Npm repository" diff --git a/workspaces/npm/plugins/npm/src/components/EntityNpmReleaseOverviewCard.tsx b/workspaces/npm/plugins/npm/src/components/EntityNpmReleaseOverviewCard.tsx index 74fa277793..5f85e00c5d 100644 --- a/workspaces/npm/plugins/npm/src/components/EntityNpmReleaseOverviewCard.tsx +++ b/workspaces/npm/plugins/npm/src/components/EntityNpmReleaseOverviewCard.tsx @@ -14,6 +14,7 @@ * limitations under the License. */ import React from 'react'; + import { MissingAnnotationEmptyState, useEntity, @@ -23,16 +24,18 @@ import { Table, type TableColumn, } from '@backstage/core-components'; + +import { NpmAnnotation } from '@backstage-community/plugin-npm-common'; + import Box from '@material-ui/core/Box'; -import useAsync from 'react-use/esm/useAsync'; import { DateTime } from 'luxon'; -import { NPM_PACKAGE_ANNOTATION } from '../annotations'; -import { API } from '../api'; + +import { usePackageInfo } from '../hooks/usePackageInfo'; interface TagRow { tag: string; version: string; - published: string; + published?: string; } const tagColumns: TableColumn<TagRow>[] = [ @@ -50,11 +53,14 @@ const tagColumns: TableColumn<TagRow>[] = [ title: 'Published', field: 'published', type: 'datetime', - render: row => ( - <time dateTime={row.published} title={row.published}> - {DateTime.fromISO(row.published).toRelative()} - </time> - ), + render: row => + row.published ? ( + <time dateTime={row.published} title={row.published}> + {DateTime.fromISO(row.published).toRelative()} + </time> + ) : ( + '-' + ), }, ]; @@ -66,19 +72,18 @@ const tagColumns: TableColumn<TagRow>[] = [ */ export const EntityNpmReleaseOverviewCard = () => { const { entity } = useEntity(); + const { packageInfo, loading, error } = usePackageInfo(); - const packageName = entity.metadata.annotations?.[NPM_PACKAGE_ANNOTATION]; - - const { - value: packageInfo, - loading, - error, - } = useAsync(() => API.fetchNpmPackage(packageName), [packageName]); + const packageName = entity.metadata.annotations?.[NpmAnnotation.PACKAGE_NAME]; + const showTags = entity.metadata.annotations?.[NpmAnnotation.SHOW_TAGS] + ?.split(',') + .map(s => s.trim()) + .filter(Boolean); if (!packageName) { return ( <MissingAnnotationEmptyState - annotation={NPM_PACKAGE_ANNOTATION} + annotation={NpmAnnotation.PACKAGE_NAME} readMoreUrl="https://backstage.io/docs/features/software-catalog/descriptor-format" /> ); @@ -87,7 +92,10 @@ export const EntityNpmReleaseOverviewCard = () => { const data: TagRow[] = []; if (packageInfo?.['dist-tags']) { for (const [tag, version] of Object.entries(packageInfo['dist-tags'])) { - const published = packageInfo.time[version]; + if (showTags && showTags.length > 0 && !showTags.includes(tag)) { + continue; + } + const published = packageInfo.time?.[version]; data.push({ tag, version, published }); } } diff --git a/workspaces/npm/plugins/npm/src/components/EntityNpmReleaseTableCard.tsx b/workspaces/npm/plugins/npm/src/components/EntityNpmReleaseTableCard.tsx index 3254a0e666..7cfc5c3547 100644 --- a/workspaces/npm/plugins/npm/src/components/EntityNpmReleaseTableCard.tsx +++ b/workspaces/npm/plugins/npm/src/components/EntityNpmReleaseTableCard.tsx @@ -14,6 +14,7 @@ * limitations under the License. */ import React from 'react'; + import { MissingAnnotationEmptyState, useEntity, @@ -23,21 +24,24 @@ import { Table, type TableColumn, } from '@backstage/core-components'; + +import { NpmAnnotation } from '@backstage-community/plugin-npm-common'; + import Box from '@material-ui/core/Box'; -import useAsync from 'react-use/esm/useAsync'; + import { DateTime } from 'luxon'; -import { NPM_PACKAGE_ANNOTATION } from '../annotations'; -import { API } from '../api'; + +import { usePackageInfo } from '../hooks/usePackageInfo'; interface TagRow { tag: string; version: string; - published: string; + published?: string; } interface TableData { version: string; - published: string; + published?: string; } const tagColumns: TableColumn<TagRow>[] = [ @@ -55,11 +59,14 @@ const tagColumns: TableColumn<TagRow>[] = [ title: 'Published', field: 'published', type: 'datetime', - render: row => ( - <time dateTime={row.published} title={row.published}> - {DateTime.fromISO(row.published).toRelative()} - </time> - ), + render: row => + row.published ? ( + <time dateTime={row.published} title={row.published}> + {DateTime.fromISO(row.published).toRelative()} + </time> + ) : ( + '-' + ), }, ]; @@ -73,11 +80,14 @@ const columns: TableColumn<TableData>[] = [ title: 'Published', field: 'published', type: 'datetime', - render: row => ( - <time dateTime={row.published} title={row.published}> - {DateTime.fromISO(row.published).toRelative()} - </time> - ), + render: row => + row.published ? ( + <time dateTime={row.published} title={row.published}> + {DateTime.fromISO(row.published).toRelative()} + </time> + ) : ( + '-' + ), }, ]; @@ -90,19 +100,18 @@ const columns: TableColumn<TableData>[] = [ */ export const EntityNpmReleaseTableCard = () => { const { entity } = useEntity(); + const { packageInfo, loading, error } = usePackageInfo(); - const packageName = entity.metadata.annotations?.[NPM_PACKAGE_ANNOTATION]; - - const { - value: packageInfo, - loading, - error, - } = useAsync(() => API.fetchNpmPackage(packageName), [packageName]); + const packageName = entity.metadata.annotations?.[NpmAnnotation.PACKAGE_NAME]; + const showTags = entity.metadata.annotations?.[NpmAnnotation.SHOW_TAGS] + ?.split(',') + .map(s => s.trim()) + .filter(Boolean); if (!packageName) { return ( <MissingAnnotationEmptyState - annotation={NPM_PACKAGE_ANNOTATION} + annotation={NpmAnnotation.PACKAGE_NAME} readMoreUrl="https://backstage.io/docs/features/software-catalog/descriptor-format" /> ); @@ -111,12 +120,16 @@ export const EntityNpmReleaseTableCard = () => { const tagData: TagRow[] = []; if (packageInfo?.['dist-tags']) { for (const [tag, version] of Object.entries(packageInfo['dist-tags'])) { - const published = packageInfo.time[version]; + if (showTags && showTags.length > 0 && !showTags.includes(tag)) { + continue; + } + const published = packageInfo.time?.[version]; tagData.push({ tag, version, published }); } } const data: TableData[] = []; + // npmjs, GitHub has a time history, GitLab not if (packageInfo?.time) { for (const [version, published] of Object.entries(packageInfo.time)) { if (version === 'created' || version === 'modified') { @@ -125,6 +138,13 @@ export const EntityNpmReleaseTableCard = () => { data.push({ version, published }); } data.reverse(); + } else if (packageInfo?.versions) { + for (const [version, _releasePackageInfo] of Object.entries( + packageInfo.versions, + )) { + data.push({ version }); + } + data.reverse(); } const emptyContent = error ? ( @@ -133,6 +153,7 @@ export const EntityNpmReleaseTableCard = () => { </Box> ) : null; + // TODO: export both tables as cards and rename `EntityNpmReleaseTableCard` to `EntityNpmReleaseContent` or `NpmReleaseEntityContent` return ( <> <Table diff --git a/workspaces/npm/plugins/npm/src/hooks/usePackageInfo.ts b/workspaces/npm/plugins/npm/src/hooks/usePackageInfo.ts new file mode 100644 index 0000000000..17ec31a296 --- /dev/null +++ b/workspaces/npm/plugins/npm/src/hooks/usePackageInfo.ts @@ -0,0 +1,63 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import useAsync from 'react-use/esm/useAsync'; + +import { configApiRef, useApi } from '@backstage/core-plugin-api'; +import { useEntity } from '@backstage/plugin-catalog-react'; +import { stringifyEntityRef } from '@backstage/catalog-model'; +import { NotFoundError } from '@backstage/errors'; + +import { + NpmAnnotation, + NpmRegistryClient, +} from '@backstage-community/plugin-npm-common'; + +import { NpmBackendApiRef } from '../api'; + +export const usePackageInfo = () => { + const config = useApi(configApiRef); + const backendApi = useApi(NpmBackendApiRef); + const { entity } = useEntity(); + const entityRef = stringifyEntityRef(entity); + + const packageName = entity.metadata.annotations?.[NpmAnnotation.PACKAGE_NAME]; + + const useBackend = + Boolean(config.getOptionalString('npm.defaultRegistry')) || + Boolean(entity.metadata.annotations?.[NpmAnnotation.REGISTRY_NAME]); + + const { + value: packageInfo, + loading, + error, + } = useAsync(() => { + if (!packageName) { + throw new NotFoundError( + `No pacakge name found for entity ref '${entityRef}'`, + ); + } + if (useBackend) { + return backendApi.getPackageInfo(entityRef); + } + return new NpmRegistryClient({}).getPackageInfo(packageName); + }, [entityRef, packageName, useBackend]); + + return { + packageInfo, + loading, + error, + }; +}; diff --git a/workspaces/npm/plugins/npm/src/index.ts b/workspaces/npm/plugins/npm/src/index.ts index 6ff0b7afbf..5452bec224 100644 --- a/workspaces/npm/plugins/npm/src/index.ts +++ b/workspaces/npm/plugins/npm/src/index.ts @@ -20,6 +20,8 @@ * @packageDocumentation */ +export { isNpmAvailable } from '@backstage-community/plugin-npm-common'; + export { npmPlugin, EntityNpmInfoCard, @@ -29,5 +31,3 @@ export { NpmReleaseOverviewCard, NpmReleaseTableCard, } from './plugin'; - -export { isNpmAvailable } from './utils/isNpmAvailable'; diff --git a/workspaces/npm/plugins/npm/src/plugin.ts b/workspaces/npm/plugins/npm/src/plugin.ts index da5b209622..c1b79b0687 100644 --- a/workspaces/npm/plugins/npm/src/plugin.ts +++ b/workspaces/npm/plugins/npm/src/plugin.ts @@ -14,11 +14,15 @@ * limitations under the License. */ import { + createApiFactory, createComponentExtension, createPlugin, + discoveryApiRef, + fetchApiRef, } from '@backstage/core-plugin-api'; import { rootRouteRef } from './routes'; +import { NpmBackendApiRef, NpmBackendClient } from './api'; /** * Backstage plugin. @@ -30,6 +34,20 @@ export const npmPlugin = createPlugin({ routes: { root: rootRouteRef, }, + apis: [ + createApiFactory({ + api: NpmBackendApiRef, + deps: { + discoveryApi: discoveryApiRef, + fetchApi: fetchApiRef, + }, + factory: ({ discoveryApi, fetchApi }) => + new NpmBackendClient({ + discoveryApi, + fetchApi, + }), + }), + ], }); /** diff --git a/workspaces/npm/yarn.lock b/workspaces/npm/yarn.lock index 83acda686a..6a65892892 100644 --- a/workspaces/npm/yarn.lock +++ b/workspaces/npm/yarn.lock @@ -2707,15 +2707,48 @@ __metadata: languageName: node linkType: hard +"@backstage-community/plugin-npm-backend@workspace:^, @backstage-community/plugin-npm-backend@workspace:plugins/npm-backend": + version: 0.0.0-use.local + resolution: "@backstage-community/plugin-npm-backend@workspace:plugins/npm-backend" + dependencies: + "@backstage-community/plugin-npm-common": "workspace:^" + "@backstage/backend-defaults": ^0.5.1 + "@backstage/backend-plugin-api": ^1.0.1 + "@backstage/backend-test-utils": ^1.0.1 + "@backstage/catalog-client": ^1.7.1 + "@backstage/cli": ^0.28.0 + "@backstage/errors": ^1.2.4 + "@backstage/plugin-catalog-node": ^1.13.1 + "@types/express": "*" + "@types/supertest": ^2.0.12 + express: ^4.17.1 + express-promise-router: ^4.1.0 + supertest: ^6.2.4 + languageName: unknown + linkType: soft + +"@backstage-community/plugin-npm-common@workspace:^, @backstage-community/plugin-npm-common@workspace:plugins/npm-common": + version: 0.0.0-use.local + resolution: "@backstage-community/plugin-npm-common@workspace:plugins/npm-common" + dependencies: + "@backstage/catalog-model": ^1.7.0 + "@backstage/cli": ^0.28.0 + "@backstage/errors": ^1.2.4 + languageName: unknown + linkType: soft + "@backstage-community/plugin-npm@workspace:^, @backstage-community/plugin-npm@workspace:plugins/npm": version: 0.0.0-use.local resolution: "@backstage-community/plugin-npm@workspace:plugins/npm" dependencies: + "@backstage-community/plugin-npm-common": "workspace:^" "@backstage/catalog-model": ^1.7.2 "@backstage/cli": ^0.29.4 "@backstage/core-components": ^0.16.2 "@backstage/core-plugin-api": ^1.10.2 "@backstage/dev-utils": ^1.1.5 + "@backstage/errors": ^1.2.4 + "@backstage/frontend-plugin-api": ^0.9.3 "@backstage/plugin-catalog-react": ^1.15.0 "@backstage/test-utils": ^1.7.3 "@backstage/theme": ^0.6.3 @@ -2754,7 +2787,7 @@ __metadata: languageName: node linkType: hard -"@backstage/backend-app-api@npm:^1.1.0": +"@backstage/backend-app-api@npm:^1.0.2, @backstage/backend-app-api@npm:^1.1.0": version: 1.1.0 resolution: "@backstage/backend-app-api@npm:1.1.0" dependencies: @@ -2868,6 +2901,83 @@ __metadata: languageName: node linkType: hard +"@backstage/backend-defaults@npm:^0.5.1": + version: 0.5.3 + resolution: "@backstage/backend-defaults@npm:0.5.3" + dependencies: + "@aws-sdk/abort-controller": ^3.347.0 + "@aws-sdk/client-codecommit": ^3.350.0 + "@aws-sdk/client-s3": ^3.350.0 + "@aws-sdk/credential-providers": ^3.350.0 + "@aws-sdk/types": ^3.347.0 + "@backstage/backend-app-api": ^1.0.2 + "@backstage/backend-dev-utils": ^0.1.5 + "@backstage/backend-plugin-api": ^1.0.2 + "@backstage/cli-common": ^0.1.15 + "@backstage/cli-node": ^0.2.10 + "@backstage/config": ^1.3.0 + "@backstage/config-loader": ^1.9.2 + "@backstage/errors": ^1.2.5 + "@backstage/integration": ^1.15.2 + "@backstage/integration-aws-node": ^0.1.13 + "@backstage/plugin-auth-node": ^0.5.4 + "@backstage/plugin-events-node": ^0.4.5 + "@backstage/plugin-permission-node": ^0.8.5 + "@backstage/types": ^1.2.0 + "@google-cloud/storage": ^7.0.0 + "@keyv/memcache": ^1.3.5 + "@keyv/redis": ^2.5.3 + "@manypkg/get-packages": ^1.1.3 + "@octokit/rest": ^19.0.3 + "@opentelemetry/api": ^1.3.0 + "@types/cors": ^2.8.6 + "@types/express": ^4.17.6 + archiver: ^7.0.0 + base64-stream: ^1.0.0 + better-sqlite3: ^11.0.0 + compression: ^1.7.4 + concat-stream: ^2.0.0 + cookie: ^0.7.0 + cors: ^2.8.5 + cron: ^3.0.0 + express: ^4.17.1 + express-promise-router: ^4.1.0 + fs-extra: ^11.2.0 + git-url-parse: ^15.0.0 + helmet: ^6.0.0 + isomorphic-git: ^1.23.0 + jose: ^5.0.0 + keyv: ^4.5.2 + knex: ^3.0.0 + lodash: ^4.17.21 + logform: ^2.3.2 + luxon: ^3.0.0 + minimatch: ^9.0.0 + minimist: ^1.2.5 + morgan: ^1.10.0 + mysql2: ^3.0.0 + node-fetch: ^2.7.0 + node-forge: ^1.3.1 + p-limit: ^3.1.0 + path-to-regexp: ^8.0.0 + pg: ^8.11.3 + pg-connection-string: ^2.3.0 + pg-format: ^1.0.4 + raw-body: ^2.4.1 + selfsigned: ^2.0.0 + stoppable: ^1.1.0 + tar: ^6.1.12 + triple-beam: ^1.4.1 + uuid: ^11.0.0 + winston: ^3.2.1 + winston-transport: ^4.5.0 + yauzl: ^3.0.0 + yn: ^4.0.0 + zod: ^3.22.4 + checksum: 92be8c95a2a41ee4c040a4046703026127a5d3194828f907e862413c5c49bc305181bdf9734970f2e95909ceba6021cc8e28513631df43e92d2d5658d4f1bcce + languageName: node + linkType: hard + "@backstage/backend-defaults@npm:^0.6.0, @backstage/backend-defaults@npm:^0.6.2": version: 0.6.2 resolution: "@backstage/backend-defaults@npm:0.6.2" @@ -2982,7 +3092,7 @@ __metadata: languageName: node linkType: hard -"@backstage/backend-plugin-api@npm:^1.0.0, @backstage/backend-plugin-api@npm:^1.1.0": +"@backstage/backend-plugin-api@npm:^1.0.0, @backstage/backend-plugin-api@npm:^1.0.1, @backstage/backend-plugin-api@npm:^1.0.2, @backstage/backend-plugin-api@npm:^1.1.0": version: 1.1.0 resolution: "@backstage/backend-plugin-api@npm:1.1.0" dependencies: @@ -3000,7 +3110,44 @@ __metadata: languageName: node linkType: hard -"@backstage/catalog-client@npm:^1.9.0": +"@backstage/backend-test-utils@npm:^1.0.1": + version: 1.2.0 + resolution: "@backstage/backend-test-utils@npm:1.2.0" + dependencies: + "@backstage/backend-app-api": ^1.1.0 + "@backstage/backend-defaults": ^0.6.0 + "@backstage/backend-plugin-api": ^1.1.0 + "@backstage/config": ^1.3.1 + "@backstage/errors": ^1.2.6 + "@backstage/plugin-auth-node": ^0.5.5 + "@backstage/plugin-events-node": ^0.4.6 + "@backstage/types": ^1.2.0 + "@keyv/memcache": ^2.0.1 + "@keyv/redis": ^4.0.1 + "@types/express": ^4.17.6 + "@types/express-serve-static-core": ^4.17.5 + "@types/keyv": ^4.2.0 + "@types/qs": ^6.9.6 + better-sqlite3: ^11.0.0 + cookie: ^0.7.0 + express: ^4.17.1 + fs-extra: ^11.0.0 + keyv: ^5.2.1 + knex: ^3.0.0 + mysql2: ^3.0.0 + pg: ^8.11.3 + pg-connection-string: ^2.3.0 + testcontainers: ^10.0.0 + textextensions: ^5.16.0 + uuid: ^11.0.0 + yn: ^4.0.0 + peerDependencies: + "@types/jest": "*" + checksum: eea00066aa2941fb06ff20db31f326b36005039202f307f427df754f2b1ed5eb67ec62aa0bbd09aa72a78f77ad11ab371bb00f2573a70186ff39aafbb01088cf + languageName: node + linkType: hard + +"@backstage/catalog-client@npm:^1.7.1, @backstage/catalog-client@npm:^1.9.0": version: 1.9.0 resolution: "@backstage/catalog-client@npm:1.9.0" dependencies: @@ -3012,7 +3159,7 @@ __metadata: languageName: node linkType: hard -"@backstage/catalog-model@npm:^1.7.2": +"@backstage/catalog-model@npm:^1.7.0, @backstage/catalog-model@npm:^1.7.2": version: 1.7.2 resolution: "@backstage/catalog-model@npm:1.7.2" dependencies: @@ -3031,7 +3178,7 @@ __metadata: languageName: node linkType: hard -"@backstage/cli-node@npm:^0.2.11": +"@backstage/cli-node@npm:^0.2.10, @backstage/cli-node@npm:^0.2.11, @backstage/cli-node@npm:^0.2.9": version: 0.2.11 resolution: "@backstage/cli-node@npm:0.2.11" dependencies: @@ -3047,6 +3194,158 @@ __metadata: languageName: node linkType: hard +"@backstage/cli@npm:^0.28.0": + version: 0.28.2 + resolution: "@backstage/cli@npm:0.28.2" + dependencies: + "@backstage/catalog-model": ^1.7.0 + "@backstage/cli-common": ^0.1.14 + "@backstage/cli-node": ^0.2.9 + "@backstage/config": ^1.2.0 + "@backstage/config-loader": ^1.9.1 + "@backstage/errors": ^1.2.4 + "@backstage/eslint-plugin": ^0.1.10 + "@backstage/integration": ^1.15.1 + "@backstage/release-manifests": ^0.0.11 + "@backstage/types": ^1.1.1 + "@manypkg/get-packages": ^1.1.3 + "@module-federation/enhanced": ^0.6.0 + "@octokit/graphql": ^5.0.0 + "@octokit/graphql-schema": ^13.7.0 + "@octokit/oauth-app": ^4.2.0 + "@octokit/request": ^6.0.0 + "@pmmmwh/react-refresh-webpack-plugin": ^0.5.7 + "@rollup/plugin-commonjs": ^26.0.0 + "@rollup/plugin-json": ^6.0.0 + "@rollup/plugin-node-resolve": ^15.0.0 + "@rollup/plugin-yaml": ^4.0.0 + "@spotify/eslint-config-base": ^15.0.0 + "@spotify/eslint-config-react": ^15.0.0 + "@spotify/eslint-config-typescript": ^15.0.0 + "@sucrase/webpack-loader": ^2.0.0 + "@svgr/core": 6.5.x + "@svgr/plugin-jsx": 6.5.x + "@svgr/plugin-svgo": 6.5.x + "@svgr/rollup": 6.5.x + "@svgr/webpack": 6.5.x + "@swc/core": ^1.3.46 + "@swc/helpers": ^0.5.0 + "@swc/jest": ^0.2.22 + "@types/jest": ^29.5.11 + "@types/webpack-env": ^1.15.2 + "@typescript-eslint/eslint-plugin": ^6.12.0 + "@typescript-eslint/parser": ^6.7.2 + "@yarnpkg/lockfile": ^1.1.0 + "@yarnpkg/parsers": ^3.0.0 + bfj: ^8.0.0 + buffer: ^6.0.3 + chalk: ^4.0.0 + chokidar: ^3.3.1 + commander: ^12.0.0 + cross-fetch: ^4.0.0 + cross-spawn: ^7.0.3 + css-loader: ^6.5.1 + ctrlc-windows: ^2.1.0 + esbuild: ^0.24.0 + esbuild-loader: ^4.0.0 + eslint: ^8.6.0 + eslint-config-prettier: ^9.0.0 + eslint-formatter-friendly: ^7.0.0 + eslint-plugin-deprecation: ^2.0.0 + eslint-plugin-import: ^2.25.4 + eslint-plugin-jest: ^28.0.0 + eslint-plugin-jsx-a11y: ^6.5.1 + eslint-plugin-react: ^7.28.0 + eslint-plugin-react-hooks: ^4.3.0 + eslint-plugin-unused-imports: ^3.0.0 + eslint-webpack-plugin: ^4.0.0 + express: ^4.17.1 + fork-ts-checker-webpack-plugin: ^9.0.0 + fs-extra: ^11.2.0 + git-url-parse: ^15.0.0 + glob: ^7.1.7 + global-agent: ^3.0.0 + globby: ^11.1.0 + handlebars: ^4.7.3 + html-webpack-plugin: ^5.3.1 + inquirer: ^8.2.0 + jest: ^29.7.0 + jest-cli: ^29.7.0 + jest-css-modules: ^2.1.0 + jest-environment-jsdom: ^29.0.2 + jest-runtime: ^29.0.2 + json-schema: ^0.4.0 + lodash: ^4.17.21 + mini-css-extract-plugin: ^2.4.2 + minimatch: ^9.0.0 + node-fetch: ^2.7.0 + node-libs-browser: ^2.2.1 + npm-packlist: ^5.0.0 + ora: ^5.3.0 + p-limit: ^3.1.0 + p-queue: ^6.6.2 + pirates: ^4.0.6 + postcss: ^8.1.0 + process: ^0.11.10 + raw-loader: ^4.0.2 + react-dev-utils: ^12.0.0-next.60 + react-refresh: ^0.14.0 + recursive-readdir: ^2.2.2 + replace-in-file: ^7.1.0 + rollup: ^4.0.0 + rollup-plugin-dts: ^6.1.0 + rollup-plugin-esbuild: ^6.1.1 + rollup-plugin-postcss: ^4.0.0 + rollup-pluginutils: ^2.8.2 + run-script-webpack-plugin: ^0.2.0 + semver: ^7.5.3 + style-loader: ^3.3.1 + sucrase: ^3.20.2 + swc-loader: ^0.2.3 + tar: ^6.1.12 + terser-webpack-plugin: ^5.1.3 + ts-morph: ^23.0.0 + util: ^0.12.3 + webpack: ^5.94.0 + webpack-dev-server: ^5.0.0 + webpack-node-externals: ^3.0.0 + yaml: ^2.0.0 + yargs: ^16.2.0 + yml-loader: ^2.1.0 + yn: ^4.0.0 + zod: ^3.22.4 + peerDependencies: + "@modyfi/vite-plugin-yaml": ^1.1.0 + "@rspack/core": ^1.0.10 + "@rspack/dev-server": ^1.0.9 + "@rspack/plugin-react-refresh": ^1.0.0 + "@vitejs/plugin-react": ^4.0.4 + vite: ^4.4.9 + vite-plugin-html: ^3.2.0 + vite-plugin-node-polyfills: ^0.22.0 + peerDependenciesMeta: + "@modyfi/vite-plugin-yaml": + optional: true + "@rspack/core": + optional: true + "@rspack/dev-server": + optional: true + "@rspack/plugin-react-refresh": + optional: true + "@vitejs/plugin-react": + optional: true + vite: + optional: true + vite-plugin-html: + optional: true + vite-plugin-node-polyfills: + optional: true + bin: + backstage-cli: bin/backstage-cli + checksum: 32e75a897a7a7b14df6ce43b66fdd5c9fb11b54b88fd3655257055536c77d38bf2d0c5fefbd44348f6250493673396c566eab695007f89d870757956ef659159 + languageName: node + linkType: hard + "@backstage/cli@npm:^0.29.4": version: 0.29.4 resolution: "@backstage/cli@npm:0.29.4" @@ -3196,7 +3495,7 @@ __metadata: languageName: node linkType: hard -"@backstage/config-loader@npm:^1.9.1, @backstage/config-loader@npm:^1.9.3, @backstage/config-loader@npm:^1.9.4": +"@backstage/config-loader@npm:^1.9.1, @backstage/config-loader@npm:^1.9.2, @backstage/config-loader@npm:^1.9.3, @backstage/config-loader@npm:^1.9.4": version: 1.9.4 resolution: "@backstage/config-loader@npm:1.9.4" dependencies: @@ -3219,7 +3518,7 @@ __metadata: languageName: node linkType: hard -"@backstage/config@npm:^1.2.0, @backstage/config@npm:^1.3.1": +"@backstage/config@npm:^1.2.0, @backstage/config@npm:^1.3.0, @backstage/config@npm:^1.3.1": version: 1.3.1 resolution: "@backstage/config@npm:1.3.1" dependencies: @@ -3394,7 +3693,7 @@ __metadata: languageName: node linkType: hard -"@backstage/errors@npm:^1.2.4, @backstage/errors@npm:^1.2.6": +"@backstage/errors@npm:^1.2.4, @backstage/errors@npm:^1.2.5, @backstage/errors@npm:^1.2.6": version: 1.2.6 resolution: "@backstage/errors@npm:1.2.6" dependencies: @@ -3511,7 +3810,7 @@ __metadata: languageName: node linkType: hard -"@backstage/integration-aws-node@npm:^0.1.12, @backstage/integration-aws-node@npm:^0.1.14": +"@backstage/integration-aws-node@npm:^0.1.12, @backstage/integration-aws-node@npm:^0.1.13, @backstage/integration-aws-node@npm:^0.1.14": version: 0.1.14 resolution: "@backstage/integration-aws-node@npm:0.1.14" dependencies: @@ -3547,7 +3846,7 @@ __metadata: languageName: node linkType: hard -"@backstage/integration@npm:^1.15.0, @backstage/integration@npm:^1.16.0": +"@backstage/integration@npm:^1.15.0, @backstage/integration@npm:^1.15.1, @backstage/integration@npm:^1.15.2, @backstage/integration@npm:^1.16.0": version: 1.16.0 resolution: "@backstage/integration@npm:1.16.0" dependencies: @@ -3965,7 +4264,7 @@ __metadata: languageName: node linkType: hard -"@backstage/plugin-auth-node@npm:^0.5.2, @backstage/plugin-auth-node@npm:^0.5.5": +"@backstage/plugin-auth-node@npm:^0.5.2, @backstage/plugin-auth-node@npm:^0.5.4, @backstage/plugin-auth-node@npm:^0.5.5": version: 0.5.5 resolution: "@backstage/plugin-auth-node@npm:0.5.5" dependencies: @@ -4168,7 +4467,7 @@ __metadata: languageName: node linkType: hard -"@backstage/plugin-catalog-node@npm:^1.15.0": +"@backstage/plugin-catalog-node@npm:^1.13.1, @backstage/plugin-catalog-node@npm:^1.15.0": version: 1.15.0 resolution: "@backstage/plugin-catalog-node@npm:1.15.0" dependencies: @@ -4267,7 +4566,7 @@ __metadata: languageName: node linkType: hard -"@backstage/plugin-events-node@npm:^0.4.6": +"@backstage/plugin-events-node@npm:^0.4.5, @backstage/plugin-events-node@npm:^0.4.6": version: 0.4.6 resolution: "@backstage/plugin-events-node@npm:0.4.6" dependencies: @@ -4360,7 +4659,7 @@ __metadata: languageName: node linkType: hard -"@backstage/plugin-permission-node@npm:^0.8.6": +"@backstage/plugin-permission-node@npm:^0.8.5, @backstage/plugin-permission-node@npm:^0.8.6": version: 0.8.6 resolution: "@backstage/plugin-permission-node@npm:0.8.6" dependencies: @@ -5158,6 +5457,15 @@ __metadata: languageName: node linkType: hard +"@backstage/release-manifests@npm:^0.0.11": + version: 0.0.11 + resolution: "@backstage/release-manifests@npm:0.0.11" + dependencies: + cross-fetch: ^4.0.0 + checksum: c03a21524436f1e423a40ac15f685b7f13ce3205e2684ce859571db3b70c78d783b3e1702ba3ffb2ba2d446f7444e8c592c6696b7c618fbf6648e91cb4c4fe07 + languageName: node + linkType: hard + "@backstage/release-manifests@npm:^0.0.12": version: 0.0.12 resolution: "@backstage/release-manifests@npm:0.0.12" @@ -6274,6 +6582,13 @@ __metadata: languageName: node linkType: hard +"@fastify/busboy@npm:^2.0.0": + version: 2.1.1 + resolution: "@fastify/busboy@npm:2.1.1" + checksum: 42c32ef75e906c9a4809c1e1930a5ca6d4ddc8d138e1a8c8ba5ea07f997db32210617d23b2e4a85fe376316a41a1a0439fc6ff2dedf5126d96f45a9d80754fb2 + languageName: node + linkType: hard + "@floating-ui/core@npm:^1.6.0": version: 1.6.8 resolution: "@floating-ui/core@npm:1.6.8" @@ -7731,6 +8046,17 @@ __metadata: languageName: node linkType: hard +"@module-federation/bridge-react-webpack-plugin@npm:0.6.16": + version: 0.6.16 + resolution: "@module-federation/bridge-react-webpack-plugin@npm:0.6.16" + dependencies: + "@module-federation/sdk": 0.6.16 + "@types/semver": 7.5.8 + semver: 7.6.3 + checksum: 9b49f8788bc741279e80cbc7b19980aa0d75e689c5ca08f1a19879d1f921f20e23e54ffc3fdc47010b90786130266d04395f46681d15ffe89f9d57e4e7575882 + languageName: node + linkType: hard + "@module-federation/bridge-react-webpack-plugin@npm:0.8.7": version: 0.8.7 resolution: "@module-federation/bridge-react-webpack-plugin@npm:0.8.7" @@ -7742,6 +8068,20 @@ __metadata: languageName: node linkType: hard +"@module-federation/data-prefetch@npm:0.6.16": + version: 0.6.16 + resolution: "@module-federation/data-prefetch@npm:0.6.16" + dependencies: + "@module-federation/runtime": 0.6.16 + "@module-federation/sdk": 0.6.16 + fs-extra: 9.1.0 + peerDependencies: + react: ">=16.9.0" + react-dom: ">=16.9.0" + checksum: cac7dc921abb1f3209e2afd7d4f21a21de525babcbd4afed69e61b2261cf7f18b6f1d9db4be005d1b60f968a03e222639e918253591c23f0be925fb84c952326 + languageName: node + linkType: hard + "@module-federation/data-prefetch@npm:0.8.7": version: 0.8.7 resolution: "@module-federation/data-prefetch@npm:0.8.7" @@ -7756,6 +8096,36 @@ __metadata: languageName: node linkType: hard +"@module-federation/dts-plugin@npm:0.6.16": + version: 0.6.16 + resolution: "@module-federation/dts-plugin@npm:0.6.16" + dependencies: + "@module-federation/error-codes": 0.6.14 + "@module-federation/managers": 0.6.16 + "@module-federation/sdk": 0.6.16 + "@module-federation/third-party-dts-extractor": 0.6.16 + adm-zip: ^0.5.10 + ansi-colors: ^4.1.3 + axios: ^1.7.4 + chalk: 3.0.0 + fs-extra: 9.1.0 + isomorphic-ws: 5.0.0 + koa: 2.15.3 + lodash.clonedeepwith: 4.5.0 + log4js: 6.9.1 + node-schedule: 2.1.1 + rambda: ^9.1.0 + ws: 8.18.0 + peerDependencies: + typescript: ^4.9.0 || ^5.0.0 + vue-tsc: ">=1.0.24" + peerDependenciesMeta: + vue-tsc: + optional: true + checksum: 6d1eae570d0234f5adfb3971c8b4b09054fc6e7bff5e06241a5a7ca699c2b22b306d74d391ccaf01ed7ef71541f87c61829342d6a65bd5234f0fcbb36a21626d + languageName: node + linkType: hard + "@module-federation/dts-plugin@npm:0.8.7": version: 0.8.7 resolution: "@module-federation/dts-plugin@npm:0.8.7" @@ -7786,6 +8156,35 @@ __metadata: languageName: node linkType: hard +"@module-federation/enhanced@npm:^0.6.0": + version: 0.6.16 + resolution: "@module-federation/enhanced@npm:0.6.16" + dependencies: + "@module-federation/bridge-react-webpack-plugin": 0.6.16 + "@module-federation/data-prefetch": 0.6.16 + "@module-federation/dts-plugin": 0.6.16 + "@module-federation/managers": 0.6.16 + "@module-federation/manifest": 0.6.16 + "@module-federation/rspack": 0.6.16 + "@module-federation/runtime-tools": 0.6.16 + "@module-federation/sdk": 0.6.16 + btoa: ^1.2.1 + upath: 2.0.1 + peerDependencies: + typescript: ^4.9.0 || ^5.0.0 + vue-tsc: ">=1.0.24" + webpack: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + vue-tsc: + optional: true + webpack: + optional: true + checksum: bb1f6566ed176e414816bfc22352f14b5ac45b1fa1655d8d403bde13145d8d0f9c54767d14b9b4fb2210eb5f406f3dd93826bcac1e2303be6bbaccb7eb78ab23 + languageName: node + linkType: hard + "@module-federation/enhanced@npm:^0.8.0": version: 0.8.7 resolution: "@module-federation/enhanced@npm:0.8.7" @@ -7817,6 +8216,13 @@ __metadata: languageName: node linkType: hard +"@module-federation/error-codes@npm:0.6.14": + version: 0.6.14 + resolution: "@module-federation/error-codes@npm:0.6.14" + checksum: d487eebb8990c0ea712dc61813f54c487c0e3549cf21239db28dfa18b5c97ae79bad5134db90aa67aee74f5af5c01d115c7aa66a66a81b098dd75f40e158fcc6 + languageName: node + linkType: hard + "@module-federation/error-codes@npm:0.8.7": version: 0.8.7 resolution: "@module-federation/error-codes@npm:0.8.7" @@ -7833,6 +8239,17 @@ __metadata: languageName: node linkType: hard +"@module-federation/managers@npm:0.6.16": + version: 0.6.16 + resolution: "@module-federation/managers@npm:0.6.16" + dependencies: + "@module-federation/sdk": 0.6.16 + find-pkg: 2.0.0 + fs-extra: 9.1.0 + checksum: 6b4e3a585aa2655134152752f2951ec1e913261510bfe714e19040da6d44a40800f7ca514d56f2ad04788d7501b886f3fcfb203900c6a25b7b8228a5459f6d33 + languageName: node + linkType: hard + "@module-federation/managers@npm:0.8.7": version: 0.8.7 resolution: "@module-federation/managers@npm:0.8.7" @@ -7844,6 +8261,19 @@ __metadata: languageName: node linkType: hard +"@module-federation/manifest@npm:0.6.16": + version: 0.6.16 + resolution: "@module-federation/manifest@npm:0.6.16" + dependencies: + "@module-federation/dts-plugin": 0.6.16 + "@module-federation/managers": 0.6.16 + "@module-federation/sdk": 0.6.16 + chalk: 3.0.0 + find-pkg: 2.0.0 + checksum: fee3254347f927756fcf4d64ede32b93326f976292d7540ebb238fad5ea81c003f030a6020d042239f1f54568ed79e5eafa21e812f763d5961c6827b60be59f7 + languageName: node + linkType: hard + "@module-federation/manifest@npm:0.8.7": version: 0.8.7 resolution: "@module-federation/manifest@npm:0.8.7" @@ -7857,6 +8287,28 @@ __metadata: languageName: node linkType: hard +"@module-federation/rspack@npm:0.6.16": + version: 0.6.16 + resolution: "@module-federation/rspack@npm:0.6.16" + dependencies: + "@module-federation/bridge-react-webpack-plugin": 0.6.16 + "@module-federation/dts-plugin": 0.6.16 + "@module-federation/managers": 0.6.16 + "@module-federation/manifest": 0.6.16 + "@module-federation/runtime-tools": 0.6.16 + "@module-federation/sdk": 0.6.16 + peerDependencies: + typescript: ^4.9.0 || ^5.0.0 + vue-tsc: ">=1.0.24" + peerDependenciesMeta: + typescript: + optional: true + vue-tsc: + optional: true + checksum: afc98f64d3270e952ff0425ddd71b13b48644306679d3a4466d38a80c855682951a4b5c1b662fa63619ffad8400d6e7029b762aefd99e7169ee431f12c278e78 + languageName: node + linkType: hard + "@module-federation/rspack@npm:0.8.7": version: 0.8.7 resolution: "@module-federation/rspack@npm:0.8.7" @@ -7891,6 +8343,16 @@ __metadata: languageName: node linkType: hard +"@module-federation/runtime-tools@npm:0.6.16": + version: 0.6.16 + resolution: "@module-federation/runtime-tools@npm:0.6.16" + dependencies: + "@module-federation/runtime": 0.6.16 + "@module-federation/webpack-bundler-runtime": 0.6.16 + checksum: 53aa76f2563e978e9f610e9276e6f3f6e73ecbf19f3cc349d0762955e748c43ec08a74f248cb697eb31d8109869f05f0f8dda1d6d082436ec246393d0011ac95 + languageName: node + linkType: hard + "@module-federation/runtime-tools@npm:0.8.7": version: 0.8.7 resolution: "@module-federation/runtime-tools@npm:0.8.7" @@ -7901,6 +8363,16 @@ __metadata: languageName: node linkType: hard +"@module-federation/runtime@npm:0.6.16": + version: 0.6.16 + resolution: "@module-federation/runtime@npm:0.6.16" + dependencies: + "@module-federation/error-codes": 0.6.14 + "@module-federation/sdk": 0.6.16 + checksum: d247b4b8ce38f84692da6a3711cdd6d35c4de7885a4639720d4df2436900d66ba2a1b815f64064b95e6aee9fb7082e4d1c6fe1e8ccecd8ddcfaef38379153bbd + languageName: node + linkType: hard + "@module-federation/runtime@npm:0.8.7": version: 0.8.7 resolution: "@module-federation/runtime@npm:0.8.7" @@ -7912,6 +8384,15 @@ __metadata: languageName: node linkType: hard +"@module-federation/sdk@npm:0.6.16": + version: 0.6.16 + resolution: "@module-federation/sdk@npm:0.6.16" + dependencies: + isomorphic-rslog: 0.0.5 + checksum: 4495af06a83cbf69da6f6c20b0e8b934382b7b5e9a1b56a3385756476e97750beeb0f4b2671dbc64a3c2ab4a5fdb1f99aafd7562f47a4894352fff75d9499ce8 + languageName: node + linkType: hard + "@module-federation/sdk@npm:0.8.7": version: 0.8.7 resolution: "@module-federation/sdk@npm:0.8.7" @@ -7921,6 +8402,17 @@ __metadata: languageName: node linkType: hard +"@module-federation/third-party-dts-extractor@npm:0.6.16": + version: 0.6.16 + resolution: "@module-federation/third-party-dts-extractor@npm:0.6.16" + dependencies: + find-pkg: 2.0.0 + fs-extra: 9.1.0 + resolve: 1.22.8 + checksum: 2f2317d3703a084a2ff11152a376276a9462954da624a6d69ab265868fb2fedeaeeb1486721f9fff0f3c15d81e3336bf71f90fabe8d4ed4cde4c4d0b5a8ff8be + languageName: node + linkType: hard + "@module-federation/third-party-dts-extractor@npm:0.8.7": version: 0.8.7 resolution: "@module-federation/third-party-dts-extractor@npm:0.8.7" @@ -7932,6 +8424,16 @@ __metadata: languageName: node linkType: hard +"@module-federation/webpack-bundler-runtime@npm:0.6.16": + version: 0.6.16 + resolution: "@module-federation/webpack-bundler-runtime@npm:0.6.16" + dependencies: + "@module-federation/runtime": 0.6.16 + "@module-federation/sdk": 0.6.16 + checksum: e78d5879eb1553c3dc96a93c7c962d9aa576b20f420fac8747fa1e3d61ab7e4ee51372924cedcd6483b829e2b4988a6f2daad4c6ddf2841c744ef69b9ba27680 + languageName: node + linkType: hard + "@module-federation/webpack-bundler-runtime@npm:0.8.7": version: 0.8.7 resolution: "@module-federation/webpack-bundler-runtime@npm:0.8.7" @@ -9899,135 +10401,135 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-android-arm-eabi@npm:4.30.0": - version: 4.30.0 - resolution: "@rollup/rollup-android-arm-eabi@npm:4.30.0" +"@rollup/rollup-android-arm-eabi@npm:4.30.1": + version: 4.30.1 + resolution: "@rollup/rollup-android-arm-eabi@npm:4.30.1" conditions: os=android & cpu=arm languageName: node linkType: hard -"@rollup/rollup-android-arm64@npm:4.30.0": - version: 4.30.0 - resolution: "@rollup/rollup-android-arm64@npm:4.30.0" +"@rollup/rollup-android-arm64@npm:4.30.1": + version: 4.30.1 + resolution: "@rollup/rollup-android-arm64@npm:4.30.1" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-darwin-arm64@npm:4.30.0": - version: 4.30.0 - resolution: "@rollup/rollup-darwin-arm64@npm:4.30.0" +"@rollup/rollup-darwin-arm64@npm:4.30.1": + version: 4.30.1 + resolution: "@rollup/rollup-darwin-arm64@npm:4.30.1" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-darwin-x64@npm:4.30.0": - version: 4.30.0 - resolution: "@rollup/rollup-darwin-x64@npm:4.30.0" +"@rollup/rollup-darwin-x64@npm:4.30.1": + version: 4.30.1 + resolution: "@rollup/rollup-darwin-x64@npm:4.30.1" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@rollup/rollup-freebsd-arm64@npm:4.30.0": - version: 4.30.0 - resolution: "@rollup/rollup-freebsd-arm64@npm:4.30.0" +"@rollup/rollup-freebsd-arm64@npm:4.30.1": + version: 4.30.1 + resolution: "@rollup/rollup-freebsd-arm64@npm:4.30.1" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-freebsd-x64@npm:4.30.0": - version: 4.30.0 - resolution: "@rollup/rollup-freebsd-x64@npm:4.30.0" +"@rollup/rollup-freebsd-x64@npm:4.30.1": + version: 4.30.1 + resolution: "@rollup/rollup-freebsd-x64@npm:4.30.1" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@rollup/rollup-linux-arm-gnueabihf@npm:4.30.0": - version: 4.30.0 - resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.30.0" +"@rollup/rollup-linux-arm-gnueabihf@npm:4.30.1": + version: 4.30.1 + resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.30.1" conditions: os=linux & cpu=arm & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-arm-musleabihf@npm:4.30.0": - version: 4.30.0 - resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.30.0" +"@rollup/rollup-linux-arm-musleabihf@npm:4.30.1": + version: 4.30.1 + resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.30.1" conditions: os=linux & cpu=arm & libc=musl languageName: node linkType: hard -"@rollup/rollup-linux-arm64-gnu@npm:4.30.0": - version: 4.30.0 - resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.30.0" +"@rollup/rollup-linux-arm64-gnu@npm:4.30.1": + version: 4.30.1 + resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.30.1" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-arm64-musl@npm:4.30.0": - version: 4.30.0 - resolution: "@rollup/rollup-linux-arm64-musl@npm:4.30.0" +"@rollup/rollup-linux-arm64-musl@npm:4.30.1": + version: 4.30.1 + resolution: "@rollup/rollup-linux-arm64-musl@npm:4.30.1" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@rollup/rollup-linux-loongarch64-gnu@npm:4.30.0": - version: 4.30.0 - resolution: "@rollup/rollup-linux-loongarch64-gnu@npm:4.30.0" +"@rollup/rollup-linux-loongarch64-gnu@npm:4.30.1": + version: 4.30.1 + resolution: "@rollup/rollup-linux-loongarch64-gnu@npm:4.30.1" conditions: os=linux & cpu=loong64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-powerpc64le-gnu@npm:4.30.0": - version: 4.30.0 - resolution: "@rollup/rollup-linux-powerpc64le-gnu@npm:4.30.0" +"@rollup/rollup-linux-powerpc64le-gnu@npm:4.30.1": + version: 4.30.1 + resolution: "@rollup/rollup-linux-powerpc64le-gnu@npm:4.30.1" conditions: os=linux & cpu=ppc64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-riscv64-gnu@npm:4.30.0": - version: 4.30.0 - resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.30.0" +"@rollup/rollup-linux-riscv64-gnu@npm:4.30.1": + version: 4.30.1 + resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.30.1" conditions: os=linux & cpu=riscv64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-s390x-gnu@npm:4.30.0": - version: 4.30.0 - resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.30.0" +"@rollup/rollup-linux-s390x-gnu@npm:4.30.1": + version: 4.30.1 + resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.30.1" conditions: os=linux & cpu=s390x & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-x64-gnu@npm:4.30.0": - version: 4.30.0 - resolution: "@rollup/rollup-linux-x64-gnu@npm:4.30.0" +"@rollup/rollup-linux-x64-gnu@npm:4.30.1": + version: 4.30.1 + resolution: "@rollup/rollup-linux-x64-gnu@npm:4.30.1" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-x64-musl@npm:4.30.0": - version: 4.30.0 - resolution: "@rollup/rollup-linux-x64-musl@npm:4.30.0" +"@rollup/rollup-linux-x64-musl@npm:4.30.1": + version: 4.30.1 + resolution: "@rollup/rollup-linux-x64-musl@npm:4.30.1" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@rollup/rollup-win32-arm64-msvc@npm:4.30.0": - version: 4.30.0 - resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.30.0" +"@rollup/rollup-win32-arm64-msvc@npm:4.30.1": + version: 4.30.1 + resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.30.1" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-win32-ia32-msvc@npm:4.30.0": - version: 4.30.0 - resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.30.0" +"@rollup/rollup-win32-ia32-msvc@npm:4.30.1": + version: 4.30.1 + resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.30.1" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@rollup/rollup-win32-x64-msvc@npm:4.30.0": - version: 4.30.0 - resolution: "@rollup/rollup-win32-x64-msvc@npm:4.30.0" +"@rollup/rollup-win32-x64-msvc@npm:4.30.1": + version: 4.30.1 + resolution: "@rollup/rollup-win32-x64-msvc@npm:4.30.1" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -12048,6 +12550,18 @@ __metadata: languageName: node linkType: hard +"@ts-morph/common@npm:~0.24.0": + version: 0.24.0 + resolution: "@ts-morph/common@npm:0.24.0" + dependencies: + fast-glob: ^3.3.2 + minimatch: ^9.0.4 + mkdirp: ^3.0.1 + path-browserify: ^1.0.1 + checksum: 793bc8a47c93ab55c6c036f94480d3b0e948661aef4bb7dbc29279b1dda2fc4fce809a88e221537867a313541842e12d1ecbd32b4769688abe1303807ec09db6 + languageName: node + linkType: hard + "@ts-morph/common@npm:~0.25.0": version: 0.25.0 resolution: "@ts-morph/common@npm:0.25.0" @@ -12219,6 +12733,13 @@ __metadata: languageName: node linkType: hard +"@types/cookiejar@npm:^2.1.5": + version: 2.1.5 + resolution: "@types/cookiejar@npm:2.1.5" + checksum: 04d5990e87b6387532d15a87d9ec9b2eb783039291193863751dcfd7fc723a3b3aa30ce4c06b03975cba58632e933772f1ff031af23eaa3ac7f94e71afa6e073 + languageName: node + linkType: hard + "@types/cors@npm:^2.8.6": version: 2.8.17 resolution: "@types/cors@npm:2.8.17" @@ -12247,7 +12768,7 @@ __metadata: languageName: node linkType: hard -"@types/dockerode@npm:^3.3.0": +"@types/dockerode@npm:^3.3.0, @types/dockerode@npm:^3.3.29": version: 3.3.31 resolution: "@types/dockerode@npm:3.3.31" dependencies: @@ -12486,6 +13007,15 @@ __metadata: languageName: node linkType: hard +"@types/keyv@npm:^4.2.0": + version: 4.2.0 + resolution: "@types/keyv@npm:4.2.0" + dependencies: + keyv: "*" + checksum: 8713da9382b9346d664866a6cab2f91b0fd479f61379af891303a618e9a2abad6f347adc38a0850540e3f2dad278427de24e7555339264fddb04d1d17d3b50e0 + languageName: node + linkType: hard + "@types/long@npm:^4.0.0": version: 4.0.2 resolution: "@types/long@npm:4.0.2" @@ -12523,6 +13053,13 @@ __metadata: languageName: node linkType: hard +"@types/methods@npm:^1.1.4": + version: 1.1.4 + resolution: "@types/methods@npm:1.1.4" + checksum: ad2a7178486f2fd167750f3eb920ab032a947ff2e26f55c86670a6038632d790b46f52e5b6ead5823f1e53fc68028f1e9ddd15cfead7903e04517c88debd72b1 + languageName: node + linkType: hard + "@types/mime@npm:^1": version: 1.3.5 resolution: "@types/mime@npm:1.3.5" @@ -12651,7 +13188,7 @@ __metadata: languageName: node linkType: hard -"@types/qs@npm:*, @types/qs@npm:^6.9.11": +"@types/qs@npm:*, @types/qs@npm:^6.9.11, @types/qs@npm:^6.9.6": version: 6.9.16 resolution: "@types/qs@npm:6.9.16" checksum: 2e8918150c12735630f7ee16b770c72949274938c30306025f68aaf977227f41fe0c698ed93db1099e04916d582ac5a1faf7e3c7061c8d885d9169f59a184b6c @@ -12802,6 +13339,15 @@ __metadata: languageName: node linkType: hard +"@types/ssh2-streams@npm:*": + version: 0.1.12 + resolution: "@types/ssh2-streams@npm:0.1.12" + dependencies: + "@types/node": "*" + checksum: aa0aa45e40cfca34b4443dafa8d28ff49196c05c71867cbf0a8cdd5127be4d8a3840819543fcad16535653ca8b0e29217671ed6500ff1e7a3ad2442c5d1b40a6 + languageName: node + linkType: hard + "@types/ssh2@npm:*": version: 1.15.1 resolution: "@types/ssh2@npm:1.15.1" @@ -12811,6 +13357,16 @@ __metadata: languageName: node linkType: hard +"@types/ssh2@npm:^0.5.48": + version: 0.5.52 + resolution: "@types/ssh2@npm:0.5.52" + dependencies: + "@types/node": "*" + "@types/ssh2-streams": "*" + checksum: bc1c76ac727ad73ddd59ba849cf0ea3ed2e930439e7a363aff24f04f29b74f9b1976369b869dc9a018223c9fb8ad041c09a0f07aea8cf46a8c920049188cddae + languageName: node + linkType: hard + "@types/stack-utils@npm:^2.0.0": version: 2.0.3 resolution: "@types/stack-utils@npm:2.0.3" @@ -12834,6 +13390,27 @@ __metadata: languageName: node linkType: hard +"@types/superagent@npm:*": + version: 8.1.9 + resolution: "@types/superagent@npm:8.1.9" + dependencies: + "@types/cookiejar": ^2.1.5 + "@types/methods": ^1.1.4 + "@types/node": "*" + form-data: ^4.0.0 + checksum: 530d8c2e87706315c82c8c9696500c40621de3353bc54ea9b104947f3530243abf54d0a49a6ae219d4947606a102ceb94bedfc43b9cc49f74069a18cbb3be8e2 + languageName: node + linkType: hard + +"@types/supertest@npm:^2.0.12": + version: 2.0.16 + resolution: "@types/supertest@npm:2.0.16" + dependencies: + "@types/superagent": "*" + checksum: 2fc998ea698e0467cdbe3bea0ebce2027ea3a45a13e51a6cecb0435f44b486faecf99c34d8702d2d7fe033e6e09fdd2b374af52ecc8d0c69a1deec66b8c0dd52 + languageName: node + linkType: hard + "@types/tern@npm:*": version: 0.23.9 resolution: "@types/tern@npm:0.23.9" @@ -13912,7 +14489,7 @@ __metadata: languageName: node linkType: hard -"archiver@npm:^7.0.0": +"archiver@npm:^7.0.0, archiver@npm:^7.0.1": version: 7.0.1 resolution: "archiver@npm:7.0.1" dependencies: @@ -14123,7 +14700,7 @@ __metadata: languageName: node linkType: hard -"asap@npm:^2.0.3": +"asap@npm:^2.0.0, asap@npm:^2.0.3": version: 2.0.6 resolution: "asap@npm:2.0.6" checksum: b296c92c4b969e973260e47523207cd5769abd27c245a68c26dc7a0fe8053c55bb04360237cb51cab1df52be939da77150ace99ad331fb7fb13b3423ed73ff3d @@ -14517,6 +15094,7 @@ __metadata: version: 0.0.0-use.local resolution: "backend@workspace:packages/backend" dependencies: + "@backstage-community/plugin-npm-backend": "workspace:^" "@backstage/backend-defaults": ^0.6.2 "@backstage/cli": ^0.29.4 "@backstage/config": ^1.3.1 @@ -14569,13 +15147,49 @@ __metadata: languageName: node linkType: hard -"bare-events@npm:^2.2.0": +"bare-events@npm:^2.0.0, bare-events@npm:^2.2.0": version: 2.5.0 resolution: "bare-events@npm:2.5.0" checksum: 5aa10716e7f33c5dfc471fd657eee2a33f2db0f78b3c83b5cdd1a45a7e7871114a69460ea96cd838807c55eb470b9e53dd0dfda8c83cced1352cc8253cebff48 languageName: node linkType: hard +"bare-fs@npm:^2.1.1": + version: 2.3.5 + resolution: "bare-fs@npm:2.3.5" + dependencies: + bare-events: ^2.0.0 + bare-path: ^2.0.0 + bare-stream: ^2.0.0 + checksum: 071b1dff94a213eaf0b41693953959bf10af2deade597a56ff206a5d833579d56bc8530aa4614bb88bf39fd6d52f2404f7c36af4695109ffa756a13837ac3d91 + languageName: node + linkType: hard + +"bare-os@npm:^2.1.0": + version: 2.4.4 + resolution: "bare-os@npm:2.4.4" + checksum: e90088a7dc0307c020350a28df8ec5564cae5a4b7a213d8509d70831d7064308e2ed31de801b68f474cb004ad3a0a66bd28c38374d270484d9025ee71af20396 + languageName: node + linkType: hard + +"bare-path@npm:^2.0.0, bare-path@npm:^2.1.0": + version: 2.1.3 + resolution: "bare-path@npm:2.1.3" + dependencies: + bare-os: ^2.1.0 + checksum: 20301aeb05b735852a396515464908e51e896922c3bb353ef2a09ff54e81ced94e6ad857bb0a36d2ce659c42bd43dd5c3d5643edd8faaf910ee9950c4e137b88 + languageName: node + linkType: hard + +"bare-stream@npm:^2.0.0": + version: 2.3.2 + resolution: "bare-stream@npm:2.3.2" + dependencies: + streamx: ^2.20.0 + checksum: 051c817f0b74617d99002a91c61e6fa2b56bff3bb329c5ab4a817287bc1f46f3aef5f13bc11201b344a91873782a45f755d3910012381f16e47feee2194fd792 + languageName: node + linkType: hard + "base64-arraybuffer@npm:^0.1.5": version: 0.1.5 resolution: "base64-arraybuffer@npm:0.1.5" @@ -15528,7 +16142,7 @@ __metadata: languageName: node linkType: hard -"code-block-writer@npm:^13.0.3": +"code-block-writer@npm:^13.0.1, code-block-writer@npm:^13.0.3": version: 13.0.3 resolution: "code-block-writer@npm:13.0.3" checksum: 8e234f0ec2db9625d5efb9f05bdae79da6559bb4d9df94a6aa79a89a7b5ae25093b70d309fc5122840c9c07995cb14b4dd3f98a30f8878e3a3372e177df79454 @@ -15782,6 +16396,13 @@ __metadata: languageName: node linkType: hard +"component-emitter@npm:^1.3.0": + version: 1.3.1 + resolution: "component-emitter@npm:1.3.1" + checksum: 94550aa462c7bd5a61c1bc480e28554aa306066930152d1b1844a0dd3845d4e5db7e261ddec62ae184913b3e59b55a2ad84093b9d3596a8f17c341514d6c483d + languageName: node + linkType: hard + "compress-commons@npm:^6.0.2": version: 6.0.2 resolution: "compress-commons@npm:6.0.2" @@ -16048,6 +16669,13 @@ __metadata: languageName: node linkType: hard +"cookiejar@npm:^2.1.4": + version: 2.1.4 + resolution: "cookiejar@npm:2.1.4" + checksum: c4442111963077dc0e5672359956d6556a195d31cbb35b528356ce5f184922b99ac48245ac05ed86cf993f7df157c56da10ab3efdadfed79778a0d9b1b092d5b + languageName: node + linkType: hard + "cookies@npm:~0.9.0": version: 0.9.1 resolution: "cookies@npm:0.9.1" @@ -16859,7 +17487,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:^4.0.0, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4": +"debug@npm:4, debug@npm:^4.0.0, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4, debug@npm:^4.3.5": version: 4.3.7 resolution: "debug@npm:4.3.7" dependencies: @@ -17186,6 +17814,16 @@ __metadata: languageName: node linkType: hard +"dezalgo@npm:^1.0.4": + version: 1.0.4 + resolution: "dezalgo@npm:1.0.4" + dependencies: + asap: ^2.0.0 + wrappy: 1 + checksum: 895389c6aead740d2ab5da4d3466d20fa30f738010a4d3f4dcccc9fc645ca31c9d10b7e1804ae489b1eb02c7986f9f1f34ba132d409b043082a86d9a4e745624 + languageName: node + linkType: hard + "diff-sequences@npm:^29.6.3": version: 29.6.3 resolution: "diff-sequences@npm:29.6.3" @@ -17250,6 +17888,27 @@ __metadata: languageName: node linkType: hard +"docker-compose@npm:^0.24.8": + version: 0.24.8 + resolution: "docker-compose@npm:0.24.8" + dependencies: + yaml: ^2.2.2 + checksum: 48f3564c46490f1f51899a144deb546b61450a76bffddb378379ac7702aa34b055e0237e0dc77507df94d7ad6f1f7daeeac27730230bce9aafe2e35efeda6b45 + languageName: node + linkType: hard + +"docker-modem@npm:^3.0.0": + version: 3.0.8 + resolution: "docker-modem@npm:3.0.8" + dependencies: + debug: ^4.1.1 + readable-stream: ^3.5.0 + split-ca: ^1.0.1 + ssh2: ^1.11.0 + checksum: e3675c9b1ad800be8fb1cb9c5621fbef20a75bfedcd6e01b69808eadd7f0165681e4e30d1700897b788a67dbf4769964fcccd19c3d66f6d2499bb7aede6b34df + languageName: node + linkType: hard + "docker-modem@npm:^5.0.3": version: 5.0.3 resolution: "docker-modem@npm:5.0.3" @@ -17262,6 +17921,17 @@ __metadata: languageName: node linkType: hard +"dockerode@npm:^3.3.5": + version: 3.3.5 + resolution: "dockerode@npm:3.3.5" + dependencies: + "@balena/dockerignore": ^1.0.2 + docker-modem: ^3.0.0 + tar-fs: ~2.0.1 + checksum: 7f6650422b07fa7ea9d5801f04b1a432634446b5fe37b995b8302b953b64e93abf1bb4596c2fb574ba47aafee685ef2ab959cc86c9654add5a26d09541bbbcc6 + languageName: node + linkType: hard + "dockerode@npm:^4.0.0": version: 4.0.2 resolution: "dockerode@npm:4.0.2" @@ -18839,7 +19509,7 @@ __metadata: languageName: node linkType: hard -"fast-safe-stringify@npm:2.1.1, fast-safe-stringify@npm:^2.0.6, fast-safe-stringify@npm:^2.0.7": +"fast-safe-stringify@npm:2.1.1, fast-safe-stringify@npm:^2.0.6, fast-safe-stringify@npm:^2.0.7, fast-safe-stringify@npm:^2.1.1": version: 2.1.1 resolution: "fast-safe-stringify@npm:2.1.1" checksum: a851cbddc451745662f8f00ddb622d6766f9bd97642dabfd9a405fb0d646d69fc0b9a1243cbf67f5f18a39f40f6fa821737651ff1bceeba06c9992ca2dc5bd3d @@ -19249,6 +19919,18 @@ __metadata: languageName: node linkType: hard +"formidable@npm:^2.1.2": + version: 2.1.2 + resolution: "formidable@npm:2.1.2" + dependencies: + dezalgo: ^1.0.4 + hexoid: ^1.0.0 + once: ^1.4.0 + qs: ^6.11.0 + checksum: 81c8e5d89f5eb873e992893468f0de22c01678ca3d315db62be0560f9de1c77d4faefc9b1f4575098eb2263b3c81ba1024833a9fc3206297ddbac88a4f69b7a8 + languageName: node + linkType: hard + "forwarded@npm:0.2.0": version: 0.2.0 resolution: "forwarded@npm:0.2.0" @@ -20233,6 +20915,13 @@ __metadata: languageName: node linkType: hard +"hexoid@npm:^1.0.0": + version: 1.0.0 + resolution: "hexoid@npm:1.0.0" + checksum: 27a148ca76a2358287f40445870116baaff4a0ed0acc99900bf167f0f708ffd82e044ff55e9949c71963852b580fc024146d3ac6d5d76b508b78d927fa48ae2d + languageName: node + linkType: hard + "hey-listen@npm:^1.0.8": version: 1.0.8 resolution: "hey-listen@npm:1.0.8" @@ -20360,7 +21049,7 @@ __metadata: languageName: node linkType: hard -"html-webpack-plugin@npm:^5.6.3": +"html-webpack-plugin@npm:^5.3.1, html-webpack-plugin@npm:^5.6.3": version: 5.6.3 resolution: "html-webpack-plugin@npm:5.6.3" dependencies: @@ -21534,6 +22223,13 @@ __metadata: languageName: node linkType: hard +"isomorphic-rslog@npm:0.0.5": + version: 0.0.5 + resolution: "isomorphic-rslog@npm:0.0.5" + checksum: ba3d8a5ca4691ae4e6ef8a50c404b94658618c87bd2ac7618946f8ea067489ee4a16a152b74afe24bcbdfe975e3b3a63e3c5149bf2a929aa781bdd7eb3f1370f + languageName: node + linkType: hard + "isomorphic-rslog@npm:0.0.7": version: 0.0.7 resolution: "isomorphic-rslog@npm:0.0.7" @@ -22811,6 +23507,15 @@ __metadata: languageName: node linkType: hard +"keyv@npm:*, keyv@npm:^5.2.1, keyv@npm:^5.2.2": + version: 5.2.3 + resolution: "keyv@npm:5.2.3" + dependencies: + "@keyv/serialize": ^1.0.2 + checksum: b317a71550431ba6238bc8c71ce9ab263560df2227ca7933f7a3f18f0fa1a931312b02951cbcce9d316689709f67c5e4a4095e8e6b9aa13d19ce82c5dd7293e2 + languageName: node + linkType: hard + "keyv@npm:^4.5.2, keyv@npm:^4.5.3": version: 4.5.4 resolution: "keyv@npm:4.5.4" @@ -22820,15 +23525,6 @@ __metadata: languageName: node linkType: hard -"keyv@npm:^5.2.1, keyv@npm:^5.2.2": - version: 5.2.3 - resolution: "keyv@npm:5.2.3" - dependencies: - "@keyv/serialize": ^1.0.2 - checksum: b317a71550431ba6238bc8c71ce9ab263560df2227ca7933f7a3f18f0fa1a931312b02951cbcce9d316689709f67c5e4a4095e8e6b9aa13d19ce82c5dd7293e2 - languageName: node - linkType: hard - "kind-of@npm:^6.0.2": version: 6.0.3 resolution: "kind-of@npm:6.0.3" @@ -23982,7 +24678,7 @@ __metadata: languageName: node linkType: hard -"methods@npm:^1.0.0, methods@npm:~1.1.2": +"methods@npm:^1.0.0, methods@npm:^1.1.2, methods@npm:~1.1.2": version: 1.1.2 resolution: "methods@npm:1.1.2" checksum: 0917ff4041fa8e2f2fda5425a955fe16ca411591fbd123c0d722fcf02b73971ed6f764d85f0a6f547ce49ee0221ce2c19a5fa692157931cecb422984f1dcd13a @@ -24372,6 +25068,15 @@ __metadata: languageName: node linkType: hard +"mime@npm:2.6.0": + version: 2.6.0 + resolution: "mime@npm:2.6.0" + bin: + mime: cli.js + checksum: 1497ba7b9f6960694268a557eae24b743fd2923da46ec392b042469f4b901721ba0adcf8b0d3c2677839d0e243b209d76e5edcbd09cfdeffa2dfb6bb4df4b862 + languageName: node + linkType: hard + "mime@npm:^3.0.0": version: 3.0.0 resolution: "mime@npm:3.0.0" @@ -24658,6 +25363,15 @@ __metadata: languageName: node linkType: hard +"mkdirp@npm:^3.0.1": + version: 3.0.1 + resolution: "mkdirp@npm:3.0.1" + bin: + mkdirp: dist/cjs/src/bin.js + checksum: 972deb188e8fb55547f1e58d66bd6b4a3623bf0c7137802582602d73e6480c1c2268dcbafbfb1be466e00cc7e56ac514d7fd9334b7cf33e3e2ab547c16f83a8d + languageName: node + linkType: hard + "mockttp@npm:^3.13.0": version: 3.15.3 resolution: "mockttp@npm:3.15.3" @@ -27208,6 +27922,26 @@ __metadata: languageName: node linkType: hard +"proper-lockfile@npm:^4.1.2": + version: 4.1.2 + resolution: "proper-lockfile@npm:4.1.2" + dependencies: + graceful-fs: ^4.2.4 + retry: ^0.12.0 + signal-exit: ^3.0.2 + checksum: 00078ee6a61c216a56a6140c7d2a98c6c733b3678503002dc073ab8beca5d50ca271de4c85fca13b9b8ee2ff546c36674d1850509b84a04a5d0363bcb8638939 + languageName: node + linkType: hard + +"properties-reader@npm:^2.3.0": + version: 2.3.0 + resolution: "properties-reader@npm:2.3.0" + dependencies: + mkdirp: ^1.0.4 + checksum: cbf59e862dc507f8ce1f8d7641ed9737119f16a1d4dad8e79f17b303aaca1c6af7d36ddfef0f649cab4d200ba4334ac159af0b238f6978a085f5b1b5126b6cc3 + languageName: node + linkType: hard + "property-expr@npm:^2.0.5": version: 2.0.6 resolution: "property-expr@npm:2.0.6" @@ -27359,7 +28093,7 @@ __metadata: languageName: node linkType: hard -"qs@npm:^6.10.1, qs@npm:^6.10.3, qs@npm:^6.12.2, qs@npm:^6.12.3, qs@npm:^6.9.4": +"qs@npm:^6.10.1, qs@npm:^6.10.3, qs@npm:^6.11.0, qs@npm:^6.12.2, qs@npm:^6.12.3, qs@npm:^6.9.4": version: 6.13.1 resolution: "qs@npm:6.13.1" dependencies: @@ -28811,29 +29545,29 @@ __metadata: languageName: node linkType: hard -"rollup@npm:^4.27.3": - version: 4.30.0 - resolution: "rollup@npm:4.30.0" - dependencies: - "@rollup/rollup-android-arm-eabi": 4.30.0 - "@rollup/rollup-android-arm64": 4.30.0 - "@rollup/rollup-darwin-arm64": 4.30.0 - "@rollup/rollup-darwin-x64": 4.30.0 - "@rollup/rollup-freebsd-arm64": 4.30.0 - "@rollup/rollup-freebsd-x64": 4.30.0 - "@rollup/rollup-linux-arm-gnueabihf": 4.30.0 - "@rollup/rollup-linux-arm-musleabihf": 4.30.0 - "@rollup/rollup-linux-arm64-gnu": 4.30.0 - "@rollup/rollup-linux-arm64-musl": 4.30.0 - "@rollup/rollup-linux-loongarch64-gnu": 4.30.0 - "@rollup/rollup-linux-powerpc64le-gnu": 4.30.0 - "@rollup/rollup-linux-riscv64-gnu": 4.30.0 - "@rollup/rollup-linux-s390x-gnu": 4.30.0 - "@rollup/rollup-linux-x64-gnu": 4.30.0 - "@rollup/rollup-linux-x64-musl": 4.30.0 - "@rollup/rollup-win32-arm64-msvc": 4.30.0 - "@rollup/rollup-win32-ia32-msvc": 4.30.0 - "@rollup/rollup-win32-x64-msvc": 4.30.0 +"rollup@npm:^4.0.0, rollup@npm:^4.27.3": + version: 4.30.1 + resolution: "rollup@npm:4.30.1" + dependencies: + "@rollup/rollup-android-arm-eabi": 4.30.1 + "@rollup/rollup-android-arm64": 4.30.1 + "@rollup/rollup-darwin-arm64": 4.30.1 + "@rollup/rollup-darwin-x64": 4.30.1 + "@rollup/rollup-freebsd-arm64": 4.30.1 + "@rollup/rollup-freebsd-x64": 4.30.1 + "@rollup/rollup-linux-arm-gnueabihf": 4.30.1 + "@rollup/rollup-linux-arm-musleabihf": 4.30.1 + "@rollup/rollup-linux-arm64-gnu": 4.30.1 + "@rollup/rollup-linux-arm64-musl": 4.30.1 + "@rollup/rollup-linux-loongarch64-gnu": 4.30.1 + "@rollup/rollup-linux-powerpc64le-gnu": 4.30.1 + "@rollup/rollup-linux-riscv64-gnu": 4.30.1 + "@rollup/rollup-linux-s390x-gnu": 4.30.1 + "@rollup/rollup-linux-x64-gnu": 4.30.1 + "@rollup/rollup-linux-x64-musl": 4.30.1 + "@rollup/rollup-win32-arm64-msvc": 4.30.1 + "@rollup/rollup-win32-ia32-msvc": 4.30.1 + "@rollup/rollup-win32-x64-msvc": 4.30.1 "@types/estree": 1.0.6 fsevents: ~2.3.2 dependenciesMeta: @@ -28879,7 +29613,7 @@ __metadata: optional: true bin: rollup: dist/bin/rollup - checksum: f862a20c2f6f2e2c56428f1315eebf255bb29b40baab3ecfebf558aaaa7f00b7544aa2f7a3b89ce3426aa4cfa6e7ec7de02dd250b0a7c1bef8b5c7fd690a052c + checksum: 4a3df04dc639f36cb2d7746c829c4957a3df54b449171280a108c32c4f578677207f330e358c48637d7414ef30c1542964641c82bebc0643d5d5baee4044542e languageName: node linkType: hard @@ -28922,6 +29656,13 @@ __metadata: languageName: node linkType: hard +"run-script-webpack-plugin@npm:^0.2.0": + version: 0.2.0 + resolution: "run-script-webpack-plugin@npm:0.2.0" + checksum: 1f5df65b726e098d602b4cc27472d9e2cd88841862f7ca2112f702b01f3c4fc1cd89b54fa63780691d988c9ab36cc9adc08a6fa056cdb9c7b85b027b21ba6cdd + languageName: node + linkType: hard + "rxjs@npm:7.8.1, rxjs@npm:^7.5.5": version: 7.8.1 resolution: "rxjs@npm:7.8.1" @@ -29111,7 +29852,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:7.6.3, semver@npm:^7.3.2, semver@npm:^7.3.5, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0": +"semver@npm:7.6.3, semver@npm:^7.3.2, semver@npm:^7.3.5, semver@npm:^7.3.8, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0": version: 7.6.3 resolution: "semver@npm:7.6.3" bin: @@ -29684,7 +30425,17 @@ __metadata: languageName: node linkType: hard -"ssh2@npm:^1.15.0": +"ssh-remote-port-forward@npm:^1.0.4": + version: 1.0.4 + resolution: "ssh-remote-port-forward@npm:1.0.4" + dependencies: + "@types/ssh2": ^0.5.48 + ssh2: ^1.4.0 + checksum: c6c04c5ddfde7cb06e9a8655a152bd28fe6771c6fe62ff0bc08be229491546c410f30b153c968b8d6817a57d38678a270c228f30143ec0fe1be546efc4f6b65a + languageName: node + linkType: hard + +"ssh2@npm:^1.11.0, ssh2@npm:^1.15.0, ssh2@npm:^1.4.0": version: 1.16.0 resolution: "ssh2@npm:1.16.0" dependencies: @@ -29920,7 +30671,7 @@ __metadata: languageName: node linkType: hard -"streamx@npm:^2.15.0": +"streamx@npm:^2.15.0, streamx@npm:^2.20.0": version: 2.20.1 resolution: "streamx@npm:2.20.1" dependencies: @@ -30302,6 +31053,34 @@ __metadata: languageName: node linkType: hard +"superagent@npm:^8.1.2": + version: 8.1.2 + resolution: "superagent@npm:8.1.2" + dependencies: + component-emitter: ^1.3.0 + cookiejar: ^2.1.4 + debug: ^4.3.4 + fast-safe-stringify: ^2.1.1 + form-data: ^4.0.0 + formidable: ^2.1.2 + methods: ^1.1.2 + mime: 2.6.0 + qs: ^6.11.0 + semver: ^7.3.8 + checksum: f3601c5ccae34d5ba684a03703394b5d25931f4ae2e1e31a1de809f88a9400e997ece037f9accf148a21c408f950dc829db1e4e23576a7f9fe0efa79fd5c9d2f + languageName: node + linkType: hard + +"supertest@npm:^6.2.4": + version: 6.3.4 + resolution: "supertest@npm:6.3.4" + dependencies: + methods: ^1.1.2 + superagent: ^8.1.2 + checksum: 875c6fa7940f21e5be9bb646579cdb030d4057bf2da643e125e1f0480add1200395d2b17e10b8e54e1009efc63e047422501e9eb30e12828668498c0910f295f + languageName: node + linkType: hard + "supports-color@npm:^5.3.0": version: 5.5.0 resolution: "supports-color@npm:5.5.0" @@ -30493,6 +31272,23 @@ __metadata: languageName: node linkType: hard +"tar-fs@npm:^3.0.6": + version: 3.0.6 + resolution: "tar-fs@npm:3.0.6" + dependencies: + bare-fs: ^2.1.1 + bare-path: ^2.1.0 + pump: ^3.0.0 + tar-stream: ^3.1.5 + dependenciesMeta: + bare-fs: + optional: true + bare-path: + optional: true + checksum: b4fa09c70f75caf05bf5cf87369cd2862f1ac5fb75c4ddf9d25d55999f7736a94b58ad679d384196cba837c5f5ff14086e060fafccef5474a16e2d3058ffa488 + languageName: node + linkType: hard + "tar-fs@npm:~2.0.1": version: 2.0.1 resolution: "tar-fs@npm:2.0.1" @@ -30518,7 +31314,7 @@ __metadata: languageName: node linkType: hard -"tar-stream@npm:^3.0.0": +"tar-stream@npm:^3.0.0, tar-stream@npm:^3.1.5": version: 3.1.7 resolution: "tar-stream@npm:3.1.7" dependencies: @@ -30626,6 +31422,29 @@ __metadata: languageName: node linkType: hard +"testcontainers@npm:^10.0.0": + version: 10.13.2 + resolution: "testcontainers@npm:10.13.2" + dependencies: + "@balena/dockerignore": ^1.0.2 + "@types/dockerode": ^3.3.29 + archiver: ^7.0.1 + async-lock: ^1.4.1 + byline: ^5.0.0 + debug: ^4.3.5 + docker-compose: ^0.24.8 + dockerode: ^3.3.5 + get-port: ^5.1.1 + proper-lockfile: ^4.1.2 + properties-reader: ^2.3.0 + ssh-remote-port-forward: ^1.0.4 + tar-fs: ^3.0.6 + tmp: ^0.2.3 + undici: ^5.28.4 + checksum: dd115745369981d159b9e74ce2461c2d7c9f3cfbe747e021c8268913b0b20beb5234cb160f22743cb40b38442dbcdfb5f985c63aa14d3b367493d0bfece6afe3 + languageName: node + linkType: hard + "text-decoder@npm:^1.1.0": version: 1.2.0 resolution: "text-decoder@npm:1.2.0" @@ -30649,6 +31468,13 @@ __metadata: languageName: node linkType: hard +"textextensions@npm:^5.16.0": + version: 5.16.0 + resolution: "textextensions@npm:5.16.0" + checksum: d2abd5c962760046aa85d9ca542bd8bdb451370fc0a5e5f807aa80dd2f50175ec10d5ce9d28ae96968aaf6a1b1bea254cf4715f24852d0dcf29c6a60af7f793c + languageName: node + linkType: hard + "thenify-all@npm:^1.0.0": version: 1.6.0 resolution: "thenify-all@npm:1.6.0" @@ -30780,6 +31606,13 @@ __metadata: languageName: node linkType: hard +"tmp@npm:^0.2.3": + version: 0.2.3 + resolution: "tmp@npm:0.2.3" + checksum: 73b5c96b6e52da7e104d9d44afb5d106bb1e16d9fa7d00dbeb9e6522e61b571fbdb165c756c62164be9a3bbe192b9b268c236d370a2a0955c7689cd2ae377b95 + languageName: node + linkType: hard + "tmpl@npm:1.0.5": version: 1.0.5 resolution: "tmpl@npm:1.0.5" @@ -31034,6 +31867,16 @@ __metadata: languageName: node linkType: hard +"ts-morph@npm:^23.0.0": + version: 23.0.0 + resolution: "ts-morph@npm:23.0.0" + dependencies: + "@ts-morph/common": ~0.24.0 + code-block-writer: ^13.0.1 + checksum: 3282eb0f8bd4577770874736c3259b97501da9a86137160b5d68f106b7848ea7b1fbccf9e198a3d930ec40c993e9951d4bfae31e2562dac8f3de0d7bb0e23615 + languageName: node + linkType: hard + "ts-morph@npm:^24.0.0": version: 24.0.0 resolution: "ts-morph@npm:24.0.0" @@ -31508,6 +32351,15 @@ __metadata: languageName: node linkType: hard +"undici@npm:^5.28.4": + version: 5.28.4 + resolution: "undici@npm:5.28.4" + dependencies: + "@fastify/busboy": ^2.0.0 + checksum: a8193132d84540e4dc1895ecc8dbaa176e8a49d26084d6fbe48a292e28397cd19ec5d13bc13e604484e76f94f6e334b2bdc740d5f06a6e50c44072818d0c19f9 + languageName: node + linkType: hard + "unicode-canonical-property-names-ecmascript@npm:^2.0.0": version: 2.0.1 resolution: "unicode-canonical-property-names-ecmascript@npm:2.0.1" @@ -32260,6 +33112,13 @@ __metadata: languageName: node linkType: hard +"webpack-node-externals@npm:^3.0.0": + version: 3.0.0 + resolution: "webpack-node-externals@npm:3.0.0" + checksum: 355080c35c821115b97dda8c93d9d0565a90a6012a532324eb0d6a64f8f0d609431fd29504fc7ce414755841ac14f601f3eef99472c2c5dc00233b504ebe73f2 + languageName: node + linkType: hard + "webpack-sources@npm:^1.4.3": version: 1.4.3 resolution: "webpack-sources@npm:1.4.3" @@ -32777,12 +33636,12 @@ __metadata: languageName: node linkType: hard -"yaml@npm:^2.0.0, yaml@npm:^2.0.0-10, yaml@npm:^2.2.1": - version: 2.5.1 - resolution: "yaml@npm:2.5.1" +"yaml@npm:^2.0.0, yaml@npm:^2.0.0-10, yaml@npm:^2.2.1, yaml@npm:^2.2.2": + version: 2.6.0 + resolution: "yaml@npm:2.6.0" bin: yaml: bin.mjs - checksum: 31275223863fbd0b47ba9d2b248fbdf085db8d899e4ca43fff8a3a009497c5741084da6871d11f40e555d61360951c4c910b98216c1325d2c94753c0036d8172 + checksum: e5e74fd75e01bde2c09333d529af9fbb5928c5f7f01bfdefdcb2bf753d4ef489a45cab4deac01c9448f55ca27e691612b81fe3c3a59bb8cb5b0069da0f92cf0b languageName: node linkType: hard