diff --git a/.changeset/big-roses-stare.md b/.changeset/big-roses-stare.md new file mode 100644 index 0000000000..442e53522e --- /dev/null +++ b/.changeset/big-roses-stare.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-msgraph': patch +--- + +export the function to read ms graph provider config diff --git a/.changeset/breezy-dogs-serve.md b/.changeset/breezy-dogs-serve.md new file mode 100644 index 0000000000..a92e5cdb0c --- /dev/null +++ b/.changeset/breezy-dogs-serve.md @@ -0,0 +1,5 @@ +--- +'@backstage/create-app': patch +--- + +Cleaned up cases where deprecated code was being used but had a new location they should be imported from diff --git a/.changeset/brown-poets-join.md b/.changeset/brown-poets-join.md new file mode 100644 index 0000000000..bc6ccbaa70 --- /dev/null +++ b/.changeset/brown-poets-join.md @@ -0,0 +1,17 @@ +--- +'@backstage/create-app': patch +--- + +`knex` has been bumped to major version 3 and `better-sqlite3` to major version 9, which deprecate node 16 support. + +You can do the same in your own Backstage repository to ensure that you get future node 18+ relevant updates, by having the following lines in your `packages/backend/package.json`: + +``` +"dependencies": { + // ... + "knex": "^3.0.0" +}, +"devDependencies": { + // ... + "better-sqlite3": "^9.0.0", +``` diff --git a/.changeset/chatty-countries-refuse.md b/.changeset/chatty-countries-refuse.md new file mode 100644 index 0000000000..d29d1a453b --- /dev/null +++ b/.changeset/chatty-countries-refuse.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-bazaar': patch +--- + +Updated Readme document in bazaar plugin diff --git a/.changeset/curvy-carpets-kneel.md b/.changeset/curvy-carpets-kneel.md new file mode 100644 index 0000000000..e6b0019edb --- /dev/null +++ b/.changeset/curvy-carpets-kneel.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-shortcuts': patch +--- + +Ensure that shortcuts aren't duplicate-checked against themselves diff --git a/.changeset/famous-plums-sit.md b/.changeset/famous-plums-sit.md new file mode 100644 index 0000000000..b85e26b87e --- /dev/null +++ b/.changeset/famous-plums-sit.md @@ -0,0 +1,6 @@ +--- +'@backstage/core-components': patch +'@backstage/plugin-catalog': patch +--- + +Fix spacing inconsistency with links and labels in headers diff --git a/.changeset/healthy-dancers-dream.md b/.changeset/healthy-dancers-dream.md new file mode 100644 index 0000000000..6a9869f03a --- /dev/null +++ b/.changeset/healthy-dancers-dream.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-app-api': patch +--- + +The options parameter of `createApp` is now optional. diff --git a/.changeset/mighty-humans-shave.md b/.changeset/mighty-humans-shave.md new file mode 100644 index 0000000000..7a4971e021 --- /dev/null +++ b/.changeset/mighty-humans-shave.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-backend-module-elasticsearch': patch +--- + +Support AWS OpenSearch Serverless search backend. Does not support `_refresh` endpoint. diff --git a/.changeset/olive-doors-begin.md b/.changeset/olive-doors-begin.md new file mode 100644 index 0000000000..5d8978964c --- /dev/null +++ b/.changeset/olive-doors-begin.md @@ -0,0 +1,24 @@ +--- +'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch +'@backstage/plugin-catalog-backend-module-unprocessed': patch +'@backstage/plugin-search-backend-module-pg': patch +'@backstage/plugin-entity-feedback-backend': patch +'@backstage/plugin-code-coverage-backend': patch +'@backstage/plugin-tech-insights-backend': patch +'@backstage/plugin-user-settings-backend': patch +'@backstage/backend-plugin-api': patch +'@backstage/backend-test-utils': patch +'@backstage/plugin-scaffolder-backend': patch +'@backstage/plugin-linguist-backend': patch +'@backstage/plugin-playlist-backend': patch +'@backstage/plugin-techdocs-backend': patch +'@backstage/backend-common': patch +'@backstage/plugin-catalog-backend': patch +'@backstage/backend-tasks': patch +'@backstage/plugin-badges-backend': patch +'@backstage/plugin-bazaar-backend': patch +'@backstage/plugin-auth-backend': patch +'@backstage/plugin-app-backend': patch +--- + +`knex` has been bumped to major version 3 and `better-sqlite3` to major version 9, which deprecate node 16 support. diff --git a/.changeset/orange-jokes-tap.md b/.changeset/orange-jokes-tap.md new file mode 100644 index 0000000000..0fd9e14a46 --- /dev/null +++ b/.changeset/orange-jokes-tap.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-app-api': patch +--- + +Implement new `AppTreeApi` diff --git a/.changeset/pretty-bats-end.md b/.changeset/pretty-bats-end.md new file mode 100644 index 0000000000..8b08c5b00f --- /dev/null +++ b/.changeset/pretty-bats-end.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-gitlab': patch +--- + +Resolved a bug affecting the retrieval of users from group members. By appending '/all' to the API call, we now include members from all inherited groups, as per Gitlab's API specifications. This change is reflected in the listSaaSUsers function. diff --git a/.changeset/selfish-flies-kneel.md b/.changeset/selfish-flies-kneel.md new file mode 100644 index 0000000000..0f13f11d11 --- /dev/null +++ b/.changeset/selfish-flies-kneel.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-app-api': patch +--- + +No longer throw error on invalid input if the child is disabled. diff --git a/.changeset/shiny-goats-flash.md b/.changeset/shiny-goats-flash.md new file mode 100644 index 0000000000..35a7ce0697 --- /dev/null +++ b/.changeset/shiny-goats-flash.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-plugin-api': patch +--- + +Add new `AppTreeApi`. diff --git a/.changeset/strange-taxis-explode.md b/.changeset/strange-taxis-explode.md new file mode 100644 index 0000000000..41bcf1895c --- /dev/null +++ b/.changeset/strange-taxis-explode.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-kubernetes-backend': patch +'@backstage/plugin-kubernetes-common': patch +--- + +Fixed the lack of `resourcequotas` as part of the Default Objects to fetch from the kubernetes api diff --git a/.changeset/thick-boats-decide.md b/.changeset/thick-boats-decide.md new file mode 100644 index 0000000000..e258962ecd --- /dev/null +++ b/.changeset/thick-boats-decide.md @@ -0,0 +1,5 @@ +--- +'@backstage/create-app': patch +--- + +Added missing node-gyp dependency to fix Docker image build diff --git a/.changeset/violet-falcons-leave.md b/.changeset/violet-falcons-leave.md new file mode 100644 index 0000000000..03b91957b1 --- /dev/null +++ b/.changeset/violet-falcons-leave.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-react': patch +--- + +Removed unnecessary `@backstage/integration` dependency, replaced by `@backstage/integration-react`. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index e4b99b3be1..a3ef40c13d 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,11 +1,8 @@ --- blank_issues_enabled: false contact_links: - - about: 'Please ask and answer usage questions in GitHub Discussions' - name: Question - url: 'https://github.com/backstage/backstage/discussions' - - about: 'Alternatively, you can use the Backstage Community Discord' - name: Chat + - about: 'Use the Backstage Community Discord for questions & discussions' + name: Questions url: 'https://discord.gg/backstage-687207715902193673' - about: 'Please check the FAQ before filing new issues' name: 'Backstage FAQ' diff --git a/.github/vale/Vocab/Backstage/accept.txt b/.github/vale/Vocab/Backstage/accept.txt index 49dd7007ba..73f6d56bb4 100644 --- a/.github/vale/Vocab/Backstage/accept.txt +++ b/.github/vale/Vocab/Backstage/accept.txt @@ -107,6 +107,7 @@ dynatrace Dynatrace ecco elasticsearch +Entra env Env esbuild @@ -196,10 +197,12 @@ Leasot lerna Lerna lightbox +Lightsail limitranges LocalStack lockdown lockfile +lookbehind lunr Luxon magiclink @@ -285,6 +288,7 @@ Podman posix postgres postpack +PR pre prebaked preconfigured @@ -292,11 +296,12 @@ prepack Preprarer productional Protobuf -proxying proxied +proxying Proxying pseudonymized pubsub +Pulumi pygments pymdownx rankdir @@ -304,6 +309,7 @@ readme Readme readonly rebase +rebasing Recharts Redash replicasets @@ -312,6 +318,7 @@ Repo repos rerender rerenders +resourcequotas reusability Reusability roadmaps @@ -425,8 +432,8 @@ unregistration untracked upsert upvote -url URIs +url URLs utils Valentina @@ -455,9 +462,3 @@ zod Zolotusky zoomable zsh -Pulumi -Lightsail -PR -rebasing -lookbehind -Entra \ No newline at end of file diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 3b017e759c..f3dc873075 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -39,7 +39,7 @@ jobs: persist-credentials: false - name: 'Run analysis' - uses: ossf/scorecard-action@483ef80eb98fb506c348f7d62e28055e49fe2398 # v2.3.0 + uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1 with: results_file: results.sarif results_format: sarif @@ -66,6 +66,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: 'Upload to code-scanning' - uses: github/codeql-action/upload-sarif@49abf0ba24d0b7953cb586944e918a0b92074c80 # v2.22.4 + uses: github/codeql-action/upload-sarif@74483a38d39275f33fcff5f35b679b5ca4a26a99 # v2.22.5 with: sarif_file: results.sarif diff --git a/.github/workflows/sync_snyk-monitor.yml b/.github/workflows/sync_snyk-monitor.yml index 9268fc4975..eda19a3a88 100644 --- a/.github/workflows/sync_snyk-monitor.yml +++ b/.github/workflows/sync_snyk-monitor.yml @@ -58,6 +58,6 @@ jobs: SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} NODE_OPTIONS: --max-old-space-size=7168 - name: Upload Snyk report - uses: github/codeql-action/upload-sarif@v2.22.4 + uses: github/codeql-action/upload-sarif@v2.22.5 with: sarif_file: snyk.sarif diff --git a/.github/workflows/verify_codeql.yml b/.github/workflows/verify_codeql.yml index 59aa41ff55..06feec23ae 100644 --- a/.github/workflows/verify_codeql.yml +++ b/.github/workflows/verify_codeql.yml @@ -55,7 +55,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2.22.4 + uses: github/codeql-action/init@v2.22.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -66,7 +66,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v2.22.4 + uses: github/codeql-action/autobuild@v2.22.5 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -80,4 +80,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2.22.4 + uses: github/codeql-action/analyze@v2.22.5 diff --git a/.github/workflows/verify_storybook.yml b/.github/workflows/verify_storybook.yml index c428375a40..4afdefb17b 100644 --- a/.github/workflows/verify_storybook.yml +++ b/.github/workflows/verify_storybook.yml @@ -51,7 +51,7 @@ jobs: - run: yarn build-storybook - - uses: chromaui/action@c7e9d129ad2b8e728e10522270e14596473a7958 # v1 + - uses: chromaui/action@d726e4e790a99e876f71b8e09d3053bfe783d6b8 # v1 with: token: ${{ secrets.GITHUB_TOKEN }} # projectToken intentionally shared to allow collaborators to run Chromatic on forks diff --git a/docs/assets/frontend-system/architecture-app.drawio.svg b/docs/assets/frontend-system/architecture-app.drawio.svg new file mode 100644 index 0000000000..ed414dde97 --- /dev/null +++ b/docs/assets/frontend-system/architecture-app.drawio.svg @@ -0,0 +1,125 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/assets/frontend-system/architecture-building-blocks.drawio.svg b/docs/assets/frontend-system/architecture-building-blocks.drawio.svg new file mode 100644 index 0000000000..5be95e354d --- /dev/null +++ b/docs/assets/frontend-system/architecture-building-blocks.drawio.svg @@ -0,0 +1,331 @@ + + + + + + + +
+
+
+ App +
+
+
+
+ + App + +
+
+ + + + +
+
+
+ Extensions +
+
+
+
+ + Extensions + +
+
+ + + + + +
+
+
+ Provide +
+
+
+
+ + Provide + +
+
+ + + + +
+
+
+ Plugins +
+
+
+
+ + Plugins + +
+
+ + + + + +
+
+
+ Instantiate +
+
+
+
+ + Instantiate + +
+
+ + + + + +
+
+
+ Install +
+
+
+
+ + Install + +
+
+ + + + +
+
+
+ Utility APIs +
+
+
+
+ + Utility APIs + +
+
+ + + + + +
+
+
+ Instantiate +
+
+
+
+ + Instantiate + +
+
+ + + + + +
+
+
+ Provide & Use +
+
+
+
+ + Provide & Use + +
+
+ + + + +
+
+
+ Extension Overrides +
+
+
+
+ + Extension Ove... + +
+
+ + + + +
+
+
+ Routes +
+
+
+
+ + Routes + +
+
+ + + + + +
+
+
+ Use +
+
+
+
+ + Use + +
+
+ + + + + +
+
+
+ Provide +
+
+
+
+ + Provide + +
+
+ + + + + +
+
+
+ Resolve +
+
+
+
+ + Resolve + +
+
+ + + + + +
+
+
+ Provide +
+
+
+
+ + Provide + +
+
+ + + + + +
+
+
+ Install +
+
+
+
+ + Install + +
+
+ + + + + +
+
+
+ Override +
+
+
+
+ + Override + +
+
+ + + + + +
+
+
+ Provide +
+
+
+
+ + Provide + +
+
+
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/assets/frontend-system/architecture-extension.drawio.svg b/docs/assets/frontend-system/architecture-extension.drawio.svg new file mode 100644 index 0000000000..d7bbf43ad0 --- /dev/null +++ b/docs/assets/frontend-system/architecture-extension.drawio.svg @@ -0,0 +1,332 @@ + + + + + + + + + + +
+
+
+ Extension +
+
+
+
+ + Extension + +
+
+ + + + +
+
+
+ Output +
+
+
+
+ + Output + +
+
+ + + + + +
+
+
+ Input 1 +
+
+
+
+ + Input 1 + +
+
+ + + + + +
+
+
+ Input 2 +
+
+
+
+ + Input 2 + +
+
+ + + + +
+
+
+ disabled +
+
+
+
+ + disabled + +
+
+ + + + + + + + + + + + +
+
+
+ Output Data +
+
+
+
+ + Output Data + +
+
+ + + + + +
+
+
+ Input Data +
+
+
+
+ + Input Data + +
+
+ + + + + + + + + +
+
+
+ id +
+
+
+
+ + id + +
+
+ + + + +
+
+
+ config schema +
+
+
+
+ + config sch... + +
+
+ + + + +
+
+
+ factory +
+
+
+
+ + factory + +
+
+ + + + + + + + + + +
+
+
+ attachTo +
+
+
+
+ + attachTo + +
+
+ + + + +
+
+
+ config +
+
+
+
+ + config + +
+
+ + + + +
+
+
+ Static +
+
+
+
+ + Static + +
+
+ + + + + +
+
+
+ Configurable +
+
+
+
+ + Configurable + +
+
+ + + + + + +
+
+
+ Extension Data A +
+
+
+
+ + Extension Data A + +
+
+ + + + + +
+
+
+ Extension Data B +
+
+
+
+ + Extension Data B + +
+
+ + + + + +
+
+
+ Extension Data C +
+
+
+
+ + Extension Data C + +
+
+
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/deployment/docker.md b/docs/deployment/docker.md index 4b29ef8a0e..c9ace49d4d 100644 --- a/docs/deployment/docker.md +++ b/docs/deployment/docker.md @@ -194,8 +194,6 @@ WORKDIR /app COPY --from=packages --chown=node:node /app . -# Stop cypress from downloading it's massive binary. -ENV CYPRESS_INSTALL_BINARY=0 RUN --mount=type=cache,target=/home/node/.cache/yarn,sharing=locked,uid=1000,gid=1000 \ yarn install --frozen-lockfile --network-timeout 600000 diff --git a/docs/features/kubernetes/configuration.md b/docs/features/kubernetes/configuration.md index b31c69eac1..07e3a8a828 100644 --- a/docs/features/kubernetes/configuration.md +++ b/docs/features/kubernetes/configuration.md @@ -452,6 +452,7 @@ Overrides for the Kubernetes object types fetched from the cluster. The default - services - configmaps - limitranges +- resourcequotas - deployments - replicasets - horizontalpodautoscalers @@ -504,6 +505,7 @@ rules: - ingresses - statefulsets - limitranges + - resourcequotas - daemonsets verbs: - get diff --git a/docs/frontend-system/architecture/01-index.md b/docs/frontend-system/architecture/01-index.md new file mode 100644 index 0000000000..380ebaa335 --- /dev/null +++ b/docs/frontend-system/architecture/01-index.md @@ -0,0 +1,51 @@ +--- +id: index +title: Frontend System Architecture +sidebar_label: Overview +# prettier-ignore +description: The structure and architecture of the new Frontend System +--- + +> **NOTE: The new frontend system is in a highly experimental phase** + +## Building Blocks + +This section introduces the high-level building blocks upon which this new +system is built. Most of these concepts exist in our current system too, although +in some cases you need to squint quite a lot to see the similarity. + +Regardless of whether you are setting up your own backstage instance, +developing plugins, or extending plugins with new features, it is +important to understand these concepts. + +The diagram below provides an overview of the different building blocks, and the other blocks that each of them interact with. + +![frontend system building blocks diagram](../../assets/frontend-system/architecture-building-blocks.drawio.svg) + +### App + +This is the app instance itself that you create and use as the root of your Backstage frontend application. It does not have any direct functionality in and of itself, but is simply responsible for wiring things together. + +### Extensions + +Extensions are the building blocks that build out both the visual and non-visual structure of the application. There are both built-in extensions provided by the app itself, as well as extensions provided by plugins. Each extension is attached to a parent with which it shares data, and can have any number of children of its own. It is up to the app to wire together all extensions into a single tree known as the app extension tree. It is from this structure that the entire app can then be instantiated and rendered. + +### Plugins + +Plugins provide the actual features inside an app. The size of a plugin can range from a tiny component to an entire new system in which other plugins can be composed and integrated. Plugins can be completely standalone, or build on top of each other to extend existing plugins and augment their features. Plugins can communicate with each other by composing their extensions, or by sharing Utility APIs and routes. + +### Extension Overrides + +In addition to the built-in extensions and extensions provided by plugins, it is also possible to install extension overrides. This is a collection of extensions with high priority that can replace existing extensions. They can for example be used to override an individual extension provided by a plugin, or install a completely new extension, such as a new app theme. + +### Utility APIs + +Utility APIs provide functionality that makes it easier to build plugins, make it possible for plugins to share functionality with other plugins, as well as serve as a customization point for integrators to change the behavior of the app. Each Utility API is defined by a TypeScript interface as well as a reference used to access the implementations. The implementations of Utility APIs are defined by extensions that are provided and can be overridden the same as any other extension. + +### Routes + +The Backstage routing system adds a layer of indirection that makes it possible for plugins to route to each other's extensions without explicit knowledge of what URL paths the extension are rendered at or if they even exist at all. It makes it possible for plugins to share routes with each other and dynamically generate concrete links at runtime. It is the responsibility of the app to resolve these links to actual URLs, but it is also possible for integrators to define their own route bindings that decide how the links should be resolved. The routing system also lets plugins define internal routes, aiding in the linking to different content in the same plugin. + +## Package structure + +TODO diff --git a/docs/frontend-system/architecture/02-app.md b/docs/frontend-system/architecture/02-app.md new file mode 100644 index 0000000000..52fd20faee --- /dev/null +++ b/docs/frontend-system/architecture/02-app.md @@ -0,0 +1,48 @@ +--- +id: apps +title: App Instances +sidebar_label: App +# prettier-ignore +description: App instances +--- + +> **NOTE: The new frontend system is in a highly experimental phase** + +## The App Instance + +The app instance is main entry point for creating a frontend app. It doesn't do much on its own, but is instead responsible for wiring things together that have been provided as features from other parts of the system. + +Below is a simple example of how to create and render an app instance: + +```ts +import ReactDOM from 'react-dom/client'; +import { createApp } from '@backstage/frontend-app-api'; + +// Create your app instance +const app = createApp({ + // Features such as plugins can be installed explicitly, but we will explore other options later on + features: [catalogPlugin], +}); + +// This creates a React element that renders the entire app +const root = app.createRoot(); + +// Just like any other React we need a root element. No server side rendering is used. +const rootEl = document.getElementById('root')!; + +ReactDOM.createRoot(rootEl).render(app); +``` + +We call `createApp` to create a new app instance, which is responsible for wiring together all of the features that we provide to the app. It also provides a set of built-in [Extensions](./03-extensions.md) that help build out the foundations of the app, as well as defaults for many other systems such as [Utility API](./06-utility-apis.md) implementations, components, icons, themes, and how to load configuration. No real work is done at the point of creating the app though, it's all deferred to the rendering of the element returned from `app.createRoot()`. + +It is possible to explicitly install features when creating the app, although typically these will instead be discovered automatically which we'll explore later on. Nevertheless these features are what build out the actual functionality of the app by providing [Extensions](./03-extensions.md). These extensions are wired together by the app into a tree structure known as the app extension tree. Each node in this tree receives data from its child nodes, and pass along data to its parent. The following diagram illustrates the shape of a small app extension tree. + +![frontend system app structure diagram](../../assets/frontend-system/architecture-app.drawio.svg) + +Each node in this tree is an extension with a parent node and children. The colored shapes represent extension data inputs and output, where each color is one unique type of data. You can see that there are both extensions that output data that is ignored by the parent, as well as extensions that accept inputs but do not have any children. There are a couple of different tools at your disposal when creating and extension that lets you define different requirements for your inputs and output, which we will cover in greater details in the [Extensions](./03-extensions.md) section. + +A common type of data that is shared between extensions is React elements and components. These can in turn be rendered by each other in their own React components, which ends up forming a parallel tree of React components that is similar in shape to that of the app extension tree. At the top of the app extension tree is a built-in root extension that among other things outputs a React element. This element also ends up being the root of the parallel React tree, and is rendered by the React element returned by `app.createRoot()`. + +## Feature Discovery + +TODO diff --git a/docs/frontend-system/architecture/03-extensions.md b/docs/frontend-system/architecture/03-extensions.md new file mode 100644 index 0000000000..3d08bf1721 --- /dev/null +++ b/docs/frontend-system/architecture/03-extensions.md @@ -0,0 +1,104 @@ +--- +id: extensions +title: Frontend Extensions +sidebar_label: Extensions +# prettier-ignore +description: Frontend extensions +--- + +> **NOTE: The new frontend system is in a highly experimental phase** + +As mentioned in the [previous section](./02-app.md), Backstage apps are built up from a tree of extensions. This section will go into more detail about what extensions are, how to create and use them, and how to create your own extensibility patterns. + +## Extension Structure + +Each extensions has a number of different properties that define how it behaves and how it interacts with other extensions and the rest of the app. Some of these properties are fixed, while others can be customized by integrators. The diagram below illustrates the structure of an extension. + +![frontend extension structure diagram](../../assets/frontend-system/architecture-extension.drawio.svg) + +### ID + +The ID of an extension is used to uniquely identity it, and it should ideally by unique across the entire Backstage ecosystem. For each frontend app instance there can only be a single extension for any given ID. Installing multiple extensions with the same ID will either result in an error or one of the extensions will override the others. The ID is also used to reference the extensions from other extensions, in configuration, and in other places such as developer tools and analytics. + +### Output + +The output of an extension is the data that it provides to its parent extension, and ultimately its contribution to the app. The output itself comes in the form of a collection of arbitrary values, anything that can be represented as a TypeScript type. However, each individual output value must be associated with a shared reference known as an extension data reference. You must also use these same references to be able to access individual output values of an extension. + +### Inputs + +The inputs of an extension define the data that it received from its children. Each extension can have multiple different inputs identified by an input name. These inputs each have their own set of data that they expect, which is defined as a collection of extension data references. An extension will only have access to the data that it has explicitly requested from each input. + +### Attachment Point + +The attachment point of an extension decides where in the app extension tree it will be located. It is defined by the ID of the parent extension, as well as the name of the input to attach to. Through the attachment point the extension will share its own output as inputs to the parent extension. An extension can only be attached to an input that matches its own output, it is an error to try to attach an extension to an input the requires data that the extension does not provide in its output. + +The attachment point is one of the configurable properties of an extension, and can be overridden by integrators. In doing so, care must be taken to make sure that one doesn't attach an extension to an incompatible input. Extensions can also only be attached to a single input and parent at a time. This means that the app extension tree can not contain any cycles, as the extension ancestry will either be terminated at the root, or be detached from it. + +### Disabled + +Each extension in the app can be disabled, meaning it will not be instantiated and its parent will effectively not see it in its inputs. When creating an extension you can also specify whether extensions should be disabled by default. This makes it possible to for example install multiple extensions in an app, but only choose to enable one or a few of them depending on the environment. + +The ordering of extensions is sometimes very important, as it may for example affect in which order they show up in the UI. When an extension is toggled from disabled to enabled through configuration it resets the ordering of the extension, pushing it to the end of the list. It is generally recommended to leave extensions as disabled by default if their order is important, allowing for the order in which their are enabled in the configuration to determine their order in the app. + +### Configuration & Configuration Schema + +Each extension can define a configuration schema that describes the configuration that it accepts. This schema is used to validate the configuration provided by integrators, but also to fill in default configuration values. The configuration itself is provided by integrators in order to customize the extension. It is not possible to provide a default configuration of an extension, this must instead be done through defaults in the configuration schema. This allows for a simpler configuration logic where multiple configurations of the same extension completely replace each other rather than being merged. + +### Factory + +The extension factory is the implementation of the extension itself. It is a function that is provided with any inputs and configuration that the extension received, and must produce the output that it defined. When an app instance starts up it will call the factory function of each extension that is part of the app, starting at leaf nodes and working its way up to the root of the app extension tree. The factory will only be called for active extensions, which is an extension that is not disabled and has an active parent. + +Extension factories should be lean and not do any heavy lifting or async work, as they are called during the initialization of the app. For example, if you need to do an expensive computation to generate your output, then prefer outputting a callback that does the computation instead. This allows the parent extension to defer the computation for later so that you avoid blocking the app startup. + +## Creating an Extensions + +Extensions are created using the `createExtension` function from `@backstage/frontend-plugin-api`. At minimum you need to provide an ID, attachment point, output definition, and a factory function. The following example shows the creation of a minimal extension: + +```tsx +const extension = createExtension({ + id: 'my-extension', + // This is the attachment point, `id` is the ID of the parent extension, + // while `input` is the name of the input to attach to. + attachTo: { id: 'my-parent', input: 'content' }, + // The output map defines the outputs of the extension. The object keys + // are only used internally to map the outputs of the factory and do + // not need to match the keys of the input. + output: { + element: coreExtensionData.reactElement, + }, + // This factory is called to instantiate the extensions and produce its output. + factory({ bind }) { + bind({ + element:
Hello World
, + }); + }, +}); +``` + +Note that while the `createExtension` is public API and used in many places, it is not typically what you use when building plugins and features. Instead there are many extension creator functions exported by both the core APIs and plugins that make it easier to create extensions for more specific usages. + +... TODO ... + +## Extension Data + +TODO + +## Extension Inputs + +TODO + +## Configuration + +TODO + +## Configuration Schema + +TODO + +## Extension Creators + +TODO + +## Extension Boundary + +TODO diff --git a/docs/frontend-system/architecture/04-plugins.md b/docs/frontend-system/architecture/04-plugins.md new file mode 100644 index 0000000000..a1e85f8407 --- /dev/null +++ b/docs/frontend-system/architecture/04-plugins.md @@ -0,0 +1,9 @@ +--- +id: plugins +title: Frontend Plugins +sidebar_label: Plugins +# prettier-ignore +description: Frontend plugins +--- + +> **NOTE: The new frontend system is in a highly experimental phase** diff --git a/docs/frontend-system/architecture/05-extension-overrides.md b/docs/frontend-system/architecture/05-extension-overrides.md new file mode 100644 index 0000000000..743a5ea59e --- /dev/null +++ b/docs/frontend-system/architecture/05-extension-overrides.md @@ -0,0 +1,9 @@ +--- +id: extension overrides +title: Frontend Extension Overrides +sidebar_label: Extension Overrides +# prettier-ignore +description: Frontend extension overrides +--- + +> **NOTE: The new frontend system is in a highly experimental phase** diff --git a/docs/frontend-system/architecture/06-utility-apis.md b/docs/frontend-system/architecture/06-utility-apis.md new file mode 100644 index 0000000000..135f60744a --- /dev/null +++ b/docs/frontend-system/architecture/06-utility-apis.md @@ -0,0 +1,11 @@ +--- +id: utility-apis +title: Utility APIs +sidebar_label: Utility APIs +# prettier-ignore +description: Utility APIs +--- + +> **NOTE: The new frontend system is in a highly experimental phase** + +See [Utility APIs docs](../../api/utility-apis.md). diff --git a/docs/frontend-system/architecture/07-routes.md b/docs/frontend-system/architecture/07-routes.md new file mode 100644 index 0000000000..354eaeda13 --- /dev/null +++ b/docs/frontend-system/architecture/07-routes.md @@ -0,0 +1,11 @@ +--- +id: routes +title: Frontend Routes +sidebar_label: Routes +# prettier-ignore +description: Frontend routes +--- + +> **NOTE: The new frontend system is in a highly experimental phase** + +See [routing system docs](../../plugins/composability.md#routing-system) diff --git a/docs/frontend-system/index.md b/docs/frontend-system/index.md new file mode 100644 index 0000000000..3970c09f00 --- /dev/null +++ b/docs/frontend-system/index.md @@ -0,0 +1,15 @@ +--- +id: index +title: The Frontend System +sidebar_label: Introduction +# prettier-ignore +description: The Frontend System +--- + +> **NOTE: The new frontend system is in a highly experimental phase** + +## Status + +The new frontend system is in an experimental phase and we do not recommend any plugins or apps to migrate. + +You can find an example app setup in [the `app-next` package](https://github.com/backstage/backstage/tree/master/packages/app-next). diff --git a/docs/integrations/azure/org.md b/docs/integrations/azure/org.md index 370678d9f9..c4968b0399 100644 --- a/docs/integrations/azure/org.md +++ b/docs/integrations/azure/org.md @@ -1,6 +1,6 @@ --- id: org -title: Microsoft Entra tenantal Data +title: Microsoft Entra Tenant Data sidebar_label: Org Data # prettier-ignore description: Importing users and groups from Microsoft Entra ID into Backstage diff --git a/microsite/data/plugins/nexus-repository-manager.yaml b/microsite/data/plugins/nexus-repository-manager.yaml new file mode 100644 index 0000000000..aca1e366e2 --- /dev/null +++ b/microsite/data/plugins/nexus-repository-manager.yaml @@ -0,0 +1,10 @@ +--- +title: Nexus Repository Manager +author: Red Hat +authorUrl: https://redhat.com +category: Image +description: View information about the build artifacts in your Nexus Repository Manager in Backstage. +documentation: https://janus-idp.io/plugins/nexus-repository-manager +iconUrl: https://janus-idp.io/images/plugins/nexus-repository-manager.svg +npmPackageName: '@janus-idp/backstage-plugin-nexus-repository-manager' +addedDate: '2023-10-25' diff --git a/microsite/yarn.lock b/microsite/yarn.lock index 0200b84675..7b3a8d5cdc 100644 --- a/microsite/yarn.lock +++ b/microsite/yarn.lock @@ -3265,9 +3265,9 @@ __metadata: linkType: hard "@types/webpack-env@npm:^1.18.0": - version: 1.18.2 - resolution: "@types/webpack-env@npm:1.18.2" - checksum: 883908ade827d35a10efc574fb6f2728a7c520d4296cf1507633ac7457204ccd697bc6c8cadac99bc5d96074a6109c658ebfde59f42ba5ba0fdfffc538892b0f + version: 1.18.3 + resolution: "@types/webpack-env@npm:1.18.3" + checksum: f24e82485d8e325b1875608766ba6dad2b2f53a0fb182bc96173b4590110c6b791163402cdf19b50c04e8c05292f227a08aafe9230b2bba52c40c5f7ceccc101 languageName: node linkType: hard diff --git a/packages/backend-common/api-report.md b/packages/backend-common/api-report.md index f4d430ccbd..4f1dcdbf81 100644 --- a/packages/backend-common/api-report.md +++ b/packages/backend-common/api-report.md @@ -32,6 +32,7 @@ import { HostDiscovery as HostDiscovery_2 } from '@backstage/backend-app-api'; import { IdentityService } from '@backstage/backend-plugin-api'; import { isChildPath } from '@backstage/cli-common'; import { Knex } from 'knex'; +import knexFactory from 'knex'; import { KubeConfig } from '@kubernetes/client-node'; import { LifecycleService } from '@backstage/backend-plugin-api'; import { LoadConfigOptionsRemote } from '@backstage/config-loader'; @@ -222,7 +223,7 @@ export function createDatabaseClient( lifecycle: LifecycleService; pluginMetadata: PluginMetadataService; }, -): Knex; +): knexFactory.Knex; // @public export function createRootLogger( diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index fad87cc3ec..f32f75291a 100644 --- a/packages/backend-common/package.json +++ b/packages/backend-common/package.json @@ -89,14 +89,14 @@ "isomorphic-git": "^1.23.0", "jose": "^4.6.0", "keyv": "^4.5.2", - "knex": "^2.0.0", + "knex": "^3.0.0", "lodash": "^4.17.21", "logform": "^2.3.2", "luxon": "^3.0.0", "minimatch": "^5.0.0", "mysql2": "^2.2.5", "node-fetch": "^2.6.7", - "pg": "^8.3.0", + "pg": "^8.11.3", "raw-body": "^2.4.1", "tar": "^6.1.12", "uuid": "^8.3.2", @@ -129,7 +129,7 @@ "@types/webpack-env": "^1.15.2", "@types/yauzl": "^2.10.0", "aws-sdk-client-mock": "^2.0.0", - "better-sqlite3": "^8.0.0", + "better-sqlite3": "^9.0.0", "http-errors": "^2.0.0", "msw": "^1.0.0", "mysql2": "^2.2.5", diff --git a/packages/backend-plugin-api/package.json b/packages/backend-plugin-api/package.json index a1f9149098..c1c26b56df 100644 --- a/packages/backend-plugin-api/package.json +++ b/packages/backend-plugin-api/package.json @@ -52,7 +52,7 @@ "@backstage/types": "workspace:^", "@types/express": "^4.17.6", "express": "^4.17.1", - "knex": "^2.0.0" + "knex": "^3.0.0" }, "devDependencies": { "@backstage/cli": "workspace:^" diff --git a/packages/backend-tasks/package.json b/packages/backend-tasks/package.json index f38a209831..37b3e925dd 100644 --- a/packages/backend-tasks/package.json +++ b/packages/backend-tasks/package.json @@ -39,7 +39,7 @@ "@opentelemetry/api": "^1.3.0", "@types/luxon": "^3.0.0", "cron": "^2.0.0", - "knex": "^2.0.0", + "knex": "^3.0.0", "lodash": "^4.17.21", "luxon": "^3.0.0", "uuid": "^8.0.0", diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json index 1216487880..e219a353ec 100644 --- a/packages/backend-test-utils/package.json +++ b/packages/backend-test-utils/package.json @@ -49,13 +49,13 @@ "@backstage/errors": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", "@backstage/types": "workspace:^", - "better-sqlite3": "^8.0.0", + "better-sqlite3": "^9.0.0", "express": "^4.17.1", "fs-extra": "^10.0.1", - "knex": "^2.0.0", + "knex": "^3.0.0", "msw": "^1.0.0", "mysql2": "^2.2.5", - "pg": "^8.3.0", + "pg": "^8.11.3", "testcontainers": "^8.1.2", "textextensions": "^5.16.0", "uuid": "^8.0.0" diff --git a/packages/backend/package.json b/packages/backend/package.json index bd28eadb8f..6b52cb8993 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -84,7 +84,7 @@ "@opentelemetry/exporter-prometheus": "^0.44.0", "@opentelemetry/sdk-metrics": "^1.13.0", "azure-devops-node-api": "^11.0.1", - "better-sqlite3": "^8.0.0", + "better-sqlite3": "^9.0.0", "dockerode": "^3.3.1", "example-app": "link:../app", "express": "^4.17.1", @@ -92,7 +92,7 @@ "express-promise-router": "^4.1.0", "luxon": "^3.0.0", "mysql2": "^2.2.5", - "pg": "^8.3.0", + "pg": "^8.11.3", "pg-connection-string": "^2.3.0", "prom-client": "^14.0.1", "winston": "^3.2.1" diff --git a/packages/core-app-api/src/apis/implementations/FetchApi/IdentityAuthInjectorFetchMiddleware.ts b/packages/core-app-api/src/apis/implementations/FetchApi/IdentityAuthInjectorFetchMiddleware.ts index 810d9e76c1..6f9733cba1 100644 --- a/packages/core-app-api/src/apis/implementations/FetchApi/IdentityAuthInjectorFetchMiddleware.ts +++ b/packages/core-app-api/src/apis/implementations/FetchApi/IdentityAuthInjectorFetchMiddleware.ts @@ -55,8 +55,12 @@ export class IdentityAuthInjectorFetchMiddleware implements FetchMiddleware { apply(next: typeof fetch): typeof fetch { return async (input, init) => { // Skip this middleware if the header already exists, or if the URL - // doesn't match any of the allowlist items, or if there was no token - const request = new Request(input, init); + // doesn't match any of the allowlist items, or if there was no token. + // NOTE(freben): The "as any" casts here and below are because of subtle + // undici type differences that happened in a node types bump. Those are + // immaterial to the code at hand at runtime, as the global fetch and + // Request are always taken from the same place. + const request = new Request(input as any, init); const { token } = await this.identityApi.getCredentials(); if ( request.headers.get(this.headerName) || @@ -64,7 +68,7 @@ export class IdentityAuthInjectorFetchMiddleware implements FetchMiddleware { !token || !this.allowUrl(request.url) ) { - return next(input, init); + return next(input as any, init); } request.headers.set(this.headerName, this.headerValue(token)); diff --git a/packages/core-app-api/src/apis/implementations/FetchApi/PluginProtocolResolverFetchMiddleware.ts b/packages/core-app-api/src/apis/implementations/FetchApi/PluginProtocolResolverFetchMiddleware.ts index ff20b594b4..e0afaed614 100644 --- a/packages/core-app-api/src/apis/implementations/FetchApi/PluginProtocolResolverFetchMiddleware.ts +++ b/packages/core-app-api/src/apis/implementations/FetchApi/PluginProtocolResolverFetchMiddleware.ts @@ -34,11 +34,15 @@ export class PluginProtocolResolverFetchMiddleware implements FetchMiddleware { apply(next: typeof fetch): typeof fetch { return async (input, init) => { - const request = new Request(input, init); + // NOTE(freben): The "as any" casts here and below are because of subtle + // undici type differences that happened in a node types bump. Those are + // immaterial to the code at hand at runtime, as the global fetch and + // Request are always taken from the same place. + const request = new Request(input as any, init); const prefix = 'plugin://'; if (!request.url.startsWith(prefix)) { - return next(input, init); + return next(input as any, init); } // Switch to a known protocol, since browser URL parsing misbehaves wildly @@ -57,7 +61,7 @@ export class PluginProtocolResolverFetchMiddleware implements FetchMiddleware { const target = `${join(base, pathname)}${search}${hash}`; return next( target, - typeof input === 'string' || isUrl(input) ? init : input, + typeof input === 'string' || isUrl(input) ? init : (input as any), ); }; } diff --git a/packages/core-components/src/layout/HeaderLabel/HeaderLabel.test.tsx b/packages/core-components/src/layout/HeaderLabel/HeaderLabel.test.tsx index 3dff1f51be..7f863d57fa 100644 --- a/packages/core-components/src/layout/HeaderLabel/HeaderLabel.test.tsx +++ b/packages/core-components/src/layout/HeaderLabel/HeaderLabel.test.tsx @@ -51,4 +51,29 @@ describe('', () => { expect(rendered.getByText('Value')).toBeInTheDocument(); expect(anchor.href).toBe('http://localhost/test'); }); + + it('should use a `p` tag if the provided value is a string', async () => { + const rendered = await renderInTestApp( + , + ); + expect(rendered.getByText('Value').tagName).toBe('P'); + }); + + it('should use a `span` tag if the provided value is not a string', async () => { + const rendered = await renderInTestApp( + Value} />, + ); + expect(rendered.getByText('Value').tagName).toBe('SPAN'); + }); + + it('should use the correct custom typography root component', async () => { + const rendered = await renderInTestApp( + , + ); + expect(rendered.container.querySelector('tr')).toBeInTheDocument(); + }); }); diff --git a/packages/core-components/src/layout/HeaderLabel/HeaderLabel.tsx b/packages/core-components/src/layout/HeaderLabel/HeaderLabel.tsx index e6ca9b720e..fdd48a5d81 100644 --- a/packages/core-components/src/layout/HeaderLabel/HeaderLabel.tsx +++ b/packages/core-components/src/layout/HeaderLabel/HeaderLabel.tsx @@ -49,12 +49,19 @@ const useStyles = makeStyles( type HeaderLabelContentProps = PropsWithChildren<{ value: React.ReactNode; className: string; + typographyRootComponent?: keyof JSX.IntrinsicElements; }>; -const HeaderLabelContent = ({ value, className }: HeaderLabelContentProps) => { +const HeaderLabelContent = ({ + value, + className, + typographyRootComponent, +}: HeaderLabelContentProps) => { return ( {value} @@ -65,6 +72,7 @@ const HeaderLabelContent = ({ value, className }: HeaderLabelContentProps) => { type HeaderLabelProps = { label: string; value?: HeaderLabelContentProps['value']; + contentTypograpyRootComponent?: HeaderLabelContentProps['typographyRootComponent']; url?: string; }; @@ -75,12 +83,13 @@ type HeaderLabelProps = { * */ export function HeaderLabel(props: HeaderLabelProps) { - const { label, value, url } = props; + const { label, value, url, contentTypograpyRootComponent } = props; const classes = useStyles(); const content = ( '} + typographyRootComponent={contentTypograpyRootComponent} /> ); return ( diff --git a/packages/create-app/src/lib/tasks.test.ts b/packages/create-app/src/lib/tasks.test.ts index c436bf5ad2..e7c406f51c 100644 --- a/packages/create-app/src/lib/tasks.test.ts +++ b/packages/create-app/src/lib/tasks.test.ts @@ -53,12 +53,15 @@ jest.mock('./versions', () => ({ '@backstage/plugin-auth-backend': '1.0.0', '@backstage/plugin-auth-node': '1.0.0', '@backstage/plugin-catalog-backend': '1.0.0', + '@backstage/plugin-catalog-backend-module-scaffolder-entity-model': '1.0.0', '@backstage/plugin-permission-common': '1.0.0', '@backstage/plugin-permission-node': '1.0.0', '@backstage/plugin-proxy-backend': '1.0.0', '@backstage/plugin-scaffolder-backend': '1.0.0', '@backstage/plugin-search-backend': '1.0.0', + '@backstage/plugin-search-backend-module-catalog': '1.0.0', '@backstage/plugin-search-backend-module-pg': '1.0.0', + '@backstage/plugin-search-backend-module-techdocs': '1.0.0', '@backstage/plugin-search-backend-node': '1.0.0', '@backstage/plugin-techdocs-backend': '1.0.0', '@backstage/app-defaults': '1.0.0', diff --git a/packages/create-app/src/lib/versions.ts b/packages/create-app/src/lib/versions.ts index 67db8b4a78..81bae3c0b8 100644 --- a/packages/create-app/src/lib/versions.ts +++ b/packages/create-app/src/lib/versions.ts @@ -55,6 +55,7 @@ import { version as pluginCatalog } from '../../../../plugins/catalog/package.js import { version as pluginCatalogCommon } from '../../../../plugins/catalog-common/package.json'; import { version as pluginCatalogReact } from '../../../../plugins/catalog-react/package.json'; import { version as pluginCatalogBackend } from '../../../../plugins/catalog-backend/package.json'; +import { version as pluginCatalogBackendModuleScaffolderEntityModel } from '../../../../plugins/catalog-backend-module-scaffolder-entity-model/package.json'; import { version as pluginCatalogGraph } from '../../../../plugins/catalog-graph/package.json'; import { version as pluginCatalogImport } from '../../../../plugins/catalog-import/package.json'; import { version as pluginCircleci } from '../../../../plugins/circleci/package.json'; @@ -72,7 +73,9 @@ import { version as pluginScaffolderBackend } from '../../../../plugins/scaffold import { version as pluginSearch } from '../../../../plugins/search/package.json'; import { version as pluginSearchReact } from '../../../../plugins/search-react/package.json'; import { version as pluginSearchBackend } from '../../../../plugins/search-backend/package.json'; +import { version as pluginSearchBackendModuleCatalog } from '../../../../plugins/search-backend-module-catalog/package.json'; import { version as pluginSearchBackendModulePg } from '../../../../plugins/search-backend-module-pg/package.json'; +import { version as pluginSearchBackendModuleTechdocs } from '../../../../plugins/search-backend-module-techdocs/package.json'; import { version as pluginSearchBackendNode } from '../../../../plugins/search-backend-node/package.json'; import { version as pluginTechRadar } from '../../../../plugins/tech-radar/package.json'; import { version as pluginTechdocs } from '../../../../plugins/techdocs/package.json'; @@ -104,6 +107,8 @@ export const packageVersions = { '@backstage/plugin-catalog-common': pluginCatalogCommon, '@backstage/plugin-catalog-react': pluginCatalogReact, '@backstage/plugin-catalog-backend': pluginCatalogBackend, + '@backstage/plugin-catalog-backend-module-scaffolder-entity-model': + pluginCatalogBackendModuleScaffolderEntityModel, '@backstage/plugin-catalog-graph': pluginCatalogGraph, '@backstage/plugin-catalog-import': pluginCatalogImport, '@backstage/plugin-circleci': pluginCircleci, @@ -121,7 +126,11 @@ export const packageVersions = { '@backstage/plugin-search': pluginSearch, '@backstage/plugin-search-react': pluginSearchReact, '@backstage/plugin-search-backend': pluginSearchBackend, + '@backstage/plugin-search-backend-module-catalog': + pluginSearchBackendModuleCatalog, '@backstage/plugin-search-backend-module-pg': pluginSearchBackendModulePg, + '@backstage/plugin-search-backend-module-techdocs': + pluginSearchBackendModuleTechdocs, '@backstage/plugin-search-backend-node': pluginSearchBackendNode, '@backstage/plugin-tech-radar': pluginTechRadar, '@backstage/plugin-techdocs': pluginTechdocs, diff --git a/packages/create-app/templates/default-app/packages/backend/package.json.hbs b/packages/create-app/templates/default-app/packages/backend/package.json.hbs index cb358db911..f3ed808afe 100644 --- a/packages/create-app/templates/default-app/packages/backend/package.json.hbs +++ b/packages/create-app/templates/default-app/packages/backend/package.json.hbs @@ -25,20 +25,24 @@ "@backstage/plugin-auth-backend": "^{{version '@backstage/plugin-auth-backend'}}", "@backstage/plugin-auth-node": "^{{version '@backstage/plugin-auth-node'}}", "@backstage/plugin-catalog-backend": "^{{version '@backstage/plugin-catalog-backend'}}", + "@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "^{{version '@backstage/plugin-catalog-backend-module-scaffolder-entity-model'}}", "@backstage/plugin-permission-common": "^{{version '@backstage/plugin-permission-common'}}", "@backstage/plugin-permission-node": "^{{version '@backstage/plugin-permission-node'}}", "@backstage/plugin-proxy-backend": "^{{version '@backstage/plugin-proxy-backend'}}", "@backstage/plugin-scaffolder-backend": "^{{version '@backstage/plugin-scaffolder-backend'}}", "@backstage/plugin-search-backend": "^{{version '@backstage/plugin-search-backend'}}", + "@backstage/plugin-search-backend-module-catalog": "^{{version '@backstage/plugin-search-backend-module-catalog'}}", "@backstage/plugin-search-backend-module-pg": "^{{version '@backstage/plugin-search-backend-module-pg'}}", + "@backstage/plugin-search-backend-module-techdocs": "^{{version '@backstage/plugin-search-backend-module-techdocs'}}", "@backstage/plugin-search-backend-node": "^{{version '@backstage/plugin-search-backend-node'}}", "@backstage/plugin-techdocs-backend": "^{{version '@backstage/plugin-techdocs-backend'}}", "app": "link:../app", - "better-sqlite3": "^8.0.0", + "better-sqlite3": "^9.0.0", "dockerode": "^3.3.1", "express": "^4.17.1", "express-promise-router": "^4.1.0", - "pg": "^8.3.0", + "node-gyp": "^9.0.0", + "pg": "^8.11.3", "winston": "^3.2.1" }, "devDependencies": { diff --git a/packages/create-app/templates/default-app/packages/backend/src/plugins/catalog.ts b/packages/create-app/templates/default-app/packages/backend/src/plugins/catalog.ts index 876cb6bccc..4decdca1c4 100644 --- a/packages/create-app/templates/default-app/packages/backend/src/plugins/catalog.ts +++ b/packages/create-app/templates/default-app/packages/backend/src/plugins/catalog.ts @@ -1,5 +1,5 @@ import { CatalogBuilder } from '@backstage/plugin-catalog-backend'; -import { ScaffolderEntitiesProcessor } from '@backstage/plugin-scaffolder-backend'; +import { ScaffolderEntitiesProcessor } from '@backstage/plugin-catalog-backend-module-scaffolder-entity-model'; import { Router } from 'express'; import { PluginEnvironment } from '../types'; diff --git a/packages/create-app/templates/default-app/packages/backend/src/plugins/search.ts.hbs b/packages/create-app/templates/default-app/packages/backend/src/plugins/search.ts.hbs index e9469dcc1f..467ac60a5a 100644 --- a/packages/create-app/templates/default-app/packages/backend/src/plugins/search.ts.hbs +++ b/packages/create-app/templates/default-app/packages/backend/src/plugins/search.ts.hbs @@ -5,8 +5,8 @@ import { LunrSearchEngine, } from '@backstage/plugin-search-backend-node'; import { PluginEnvironment } from '../types'; -import { DefaultCatalogCollatorFactory } from '@backstage/plugin-catalog-backend'; -import { DefaultTechDocsCollatorFactory } from '@backstage/plugin-techdocs-backend'; +import { DefaultCatalogCollatorFactory } from '@backstage/plugin-search-backend-module-catalog'; +import { DefaultTechDocsCollatorFactory } from '@backstage/plugin-search-backend-module-techdocs'; import { Router } from 'express'; export default async function createPlugin( diff --git a/packages/frontend-app-api/api-report.md b/packages/frontend-app-api/api-report.md index 11c9ac03c5..3d6d936018 100644 --- a/packages/frontend-app-api/api-report.md +++ b/packages/frontend-app-api/api-report.md @@ -27,7 +27,7 @@ export type AppRouteBinder = < ) => void; // @public (undocumented) -export function createApp(options: { +export function createApp(options?: { features?: (BackstagePlugin | ExtensionOverrides)[]; configLoader?: () => Promise; bindRoutes?(context: { bind: AppRouteBinder }): void; diff --git a/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.ts b/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.ts index 5700bf4eae..43955328a8 100644 --- a/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.ts +++ b/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.ts @@ -18,7 +18,7 @@ import { RouteRef, coreExtensionData } from '@backstage/frontend-plugin-api'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports import { toLegacyPlugin } from '../wiring/createApp'; import { BackstageRouteObject } from './types'; -import { AppNode } from '../tree'; +import { AppNode } from '@backstage/frontend-plugin-api'; // We always add a child that matches all subroutes but without any route refs. This makes // sure that we're always able to match each route no matter how deep the navigation goes. diff --git a/packages/frontend-app-api/src/tree/createAppTree.ts b/packages/frontend-app-api/src/tree/createAppTree.ts index 2c36d56bf7..950669febd 100644 --- a/packages/frontend-app-api/src/tree/createAppTree.ts +++ b/packages/frontend-app-api/src/tree/createAppTree.ts @@ -22,7 +22,7 @@ import { import { readAppExtensionsConfig } from './readAppExtensionsConfig'; import { resolveAppTree } from './resolveAppTree'; import { resolveAppNodeSpecs } from './resolveAppNodeSpecs'; -import { AppTree } from './types'; +import { AppTree } from '@backstage/frontend-plugin-api'; import { Config } from '@backstage/config'; import { instantiateAppNodeTree } from './instantiateAppNodeTree'; diff --git a/packages/frontend-app-api/src/tree/index.ts b/packages/frontend-app-api/src/tree/index.ts index c864e86a7a..4b5ad5e867 100644 --- a/packages/frontend-app-api/src/tree/index.ts +++ b/packages/frontend-app-api/src/tree/index.ts @@ -14,10 +14,4 @@ * limitations under the License. */ -export type { - AppNode, - AppNodeEdges, - AppNodeInstance, - AppNodeSpec, -} from './types'; export { createAppTree } from './createAppTree'; diff --git a/packages/frontend-app-api/src/tree/instantiateAppNodeTree.test.ts b/packages/frontend-app-api/src/tree/instantiateAppNodeTree.test.ts index 2f4a112166..68a95fa1fe 100644 --- a/packages/frontend-app-api/src/tree/instantiateAppNodeTree.test.ts +++ b/packages/frontend-app-api/src/tree/instantiateAppNodeTree.test.ts @@ -25,7 +25,7 @@ import { createAppNodeInstance, instantiateAppNodeTree, } from './instantiateAppNodeTree'; -import { AppNodeInstance, AppNodeSpec } from './types'; +import { AppNodeInstance, AppNodeSpec } from '@backstage/frontend-plugin-api'; import { resolveAppTree } from './resolveAppTree'; const testDataRef = createExtensionDataRef('test'); @@ -167,7 +167,8 @@ describe('instantiateAppNodeTree', () => { { ...makeSpec(simpleExtension), id: 'child-node', - attachTo: { id: 'root-node', input: 'test' }, + // Using an invalid input should not be an error when disabled + attachTo: { id: 'root-node', input: 'invalid' }, disabled: true, }, ]); diff --git a/packages/frontend-app-api/src/tree/instantiateAppNodeTree.ts b/packages/frontend-app-api/src/tree/instantiateAppNodeTree.ts index b6e4179867..003abbb97e 100644 --- a/packages/frontend-app-api/src/tree/instantiateAppNodeTree.ts +++ b/packages/frontend-app-api/src/tree/instantiateAppNodeTree.ts @@ -20,7 +20,11 @@ import { ExtensionDataRef, } from '@backstage/frontend-plugin-api'; import mapValues from 'lodash/mapValues'; -import { AppNode, AppNodeInstance, AppNodeSpec } from './types'; +import { + AppNode, + AppNodeInstance, + AppNodeSpec, +} from '@backstage/frontend-plugin-api'; type Mutable = { -readonly [P in keyof T]: T[P]; @@ -176,7 +180,9 @@ export function instantiateAppNodeTree(rootNode: AppNode): void { } return [{ id: child.spec.id, instance: childInstance }]; }); - instantiatedAttachments.set(input, instantiatedChildren); + if (instantiatedChildren.length > 0) { + instantiatedAttachments.set(input, instantiatedChildren); + } } (node as Mutable).instance = createAppNodeInstance({ diff --git a/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.ts b/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.ts index b1a4760296..0a024c0a3f 100644 --- a/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.ts +++ b/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.ts @@ -22,7 +22,7 @@ import { // eslint-disable-next-line @backstage/no-relative-monorepo-imports import { toInternalExtensionOverrides } from '../../../frontend-plugin-api/src/wiring/createExtensionOverrides'; import { ExtensionParameters } from './readAppExtensionsConfig'; -import { AppNodeSpec } from './types'; +import { AppNodeSpec } from '@backstage/frontend-plugin-api'; /** @internal */ export function resolveAppNodeSpecs(options: { diff --git a/packages/frontend-app-api/src/tree/resolveAppTree.ts b/packages/frontend-app-api/src/tree/resolveAppTree.ts index e1665a01fd..24948373bf 100644 --- a/packages/frontend-app-api/src/tree/resolveAppTree.ts +++ b/packages/frontend-app-api/src/tree/resolveAppTree.ts @@ -14,7 +14,12 @@ * limitations under the License. */ -import { AppTree, AppNode, AppNodeInstance, AppNodeSpec } from './types'; +import { + AppTree, + AppNode, + AppNodeInstance, + AppNodeSpec, +} from '@backstage/frontend-plugin-api'; function indent(str: string) { return str.replace(/^/gm, ' '); diff --git a/packages/frontend-app-api/src/wiring/createApp.test.tsx b/packages/frontend-app-api/src/wiring/createApp.test.tsx index e9fb48f957..80d9f846f0 100644 --- a/packages/frontend-app-api/src/wiring/createApp.test.tsx +++ b/packages/frontend-app-api/src/wiring/createApp.test.tsx @@ -15,6 +15,8 @@ */ import { + AppTreeApi, + appTreeApiRef, createPageExtension, createPlugin, createThemeExtension, @@ -23,6 +25,7 @@ import { screen, waitFor } from '@testing-library/react'; import { createApp } from './createApp'; import { MockConfigApi, renderWithEffects } from '@backstage/test-utils'; import React from 'react'; +import { useApi } from '@backstage/core-plugin-api'; describe('createApp', () => { it('should allow themes to be installed', async () => { @@ -90,4 +93,58 @@ describe('createApp', () => { expect(screen.getByText('Last Page')).toBeInTheDocument(), ); }); + + it('should make the app structure available through the AppTreeApi', async () => { + let appTreeApi: AppTreeApi | undefined = undefined; + + const app = createApp({ + configLoader: async () => new MockConfigApi({}), + features: [ + createPlugin({ + id: 'my-plugin', + extensions: [ + createPageExtension({ + id: 'plugin.my-plugin.page', + defaultPath: '/', + loader: async () => { + const Component = () => { + appTreeApi = useApi(appTreeApiRef); + return
My Plugin Page
; + }; + return ; + }, + }), + ], + }), + ], + }); + + await renderWithEffects(app.createRoot()); + + expect(appTreeApi).toBeDefined(); + const { tree } = appTreeApi!.getTree(); + + expect(String(tree.root)).toMatchInlineSnapshot(` + " + root [ + + content [ + + routes [ + + ] + + ] + nav [ + + ] + + ] + themes [ + + + ] + " + `); + }); }); diff --git a/packages/frontend-app-api/src/wiring/createApp.tsx b/packages/frontend-app-api/src/wiring/createApp.tsx index d726773fd3..ca0e1d60d1 100644 --- a/packages/frontend-app-api/src/wiring/createApp.tsx +++ b/packages/frontend-app-api/src/wiring/createApp.tsx @@ -17,6 +17,8 @@ import React, { JSX } from 'react'; import { ConfigReader, Config } from '@backstage/config'; import { + AppTree, + appTreeApiRef, BackstagePlugin, coreExtensionData, ExtensionDataRef, @@ -87,7 +89,8 @@ import { AppRouteBinder } from '../routing'; import { RoutingProvider } from '../routing/RoutingProvider'; import { resolveRouteBindings } from '../routing/resolveRouteBindings'; import { collectRouteIds } from '../routing/collectRouteIds'; -import { AppNode, createAppTree } from '../tree'; +import { createAppTree } from '../tree'; +import { AppNode } from '@backstage/frontend-plugin-api'; const builtinExtensions = [ Core, @@ -222,7 +225,7 @@ function deduplicateFeatures( } /** @public */ -export function createApp(options: { +export function createApp(options?: { features?: (BackstagePlugin | ExtensionOverrides)[]; configLoader?: () => Promise; bindRoutes?(context: { bind: AppRouteBinder }): void; @@ -240,11 +243,11 @@ export function createApp(options: { ); const discoveredFeatures = getAvailableFeatures(config); - const loadedFeatures = (await options.featureLoader?.({ config })) ?? []; + const loadedFeatures = (await options?.featureLoader?.({ config })) ?? []; const allFeatures = deduplicateFeatures([ ...discoveredFeatures, ...loadedFeatures, - ...(options.features ?? []), + ...(options?.features ?? []), ]); const tree = createAppTree({ @@ -262,13 +265,13 @@ export function createApp(options: { const routeIds = collectRouteIds(allFeatures); const App = () => ( - + e.instance?.getData(coreExtensionData.apiFactory)) .filter((x): x is AnyApiFactory => !!x) ?? []; const themeExtensions = - core.edges.attachments + tree.root.edges.attachments .get('themes') ?.map(e => e.instance?.getData(coreExtensionData.theme)) .filter((x): x is AppTheme => !!x) ?? []; @@ -414,6 +417,14 @@ function createApiHolder(core: AppNode, configApi: ConfigApi): ApiHolder { }, }); + factoryRegistry.register('static', { + api: appTreeApiRef, + deps: {}, + factory: () => ({ + getTree: () => ({ tree }), + }), + }); + factoryRegistry.register('static', { api: appThemeApiRef, deps: {}, diff --git a/packages/frontend-plugin-api/api-report.md b/packages/frontend-plugin-api/api-report.md index 250ce5f676..794da9617b 100644 --- a/packages/frontend-plugin-api/api-report.md +++ b/packages/frontend-plugin-api/api-report.md @@ -7,6 +7,7 @@ import { AnyApiFactory } from '@backstage/core-plugin-api'; import { AnyApiRef } from '@backstage/core-plugin-api'; +import { ApiRef } from '@backstage/core-plugin-api'; import { AppTheme } from '@backstage/core-plugin-api'; import { IconComponent } from '@backstage/core-plugin-api'; import { JsonObject } from '@backstage/types'; @@ -55,6 +56,66 @@ export type AnyRoutes = { [name in string]: RouteRef; }; +// @public +export interface AppNode { + readonly edges: AppNodeEdges; + readonly instance?: AppNodeInstance; + readonly spec: AppNodeSpec; +} + +// @public +export interface AppNodeEdges { + // (undocumented) + readonly attachedTo?: { + node: AppNode; + input: string; + }; + // (undocumented) + readonly attachments: ReadonlyMap; +} + +// @public +export interface AppNodeInstance { + getData(ref: ExtensionDataRef): T | undefined; + getDataRefs(): Iterable>; +} + +// @public +export interface AppNodeSpec { + // (undocumented) + readonly attachTo: { + id: string; + input: string; + }; + // (undocumented) + readonly config?: unknown; + // (undocumented) + readonly disabled: boolean; + // (undocumented) + readonly extension: Extension; + // (undocumented) + readonly id: string; + // (undocumented) + readonly source?: BackstagePlugin; +} + +// @public +export interface AppTree { + readonly nodes: ReadonlyMap; + readonly orphans: Iterable; + readonly root: AppNode; +} + +// @public +export interface AppTreeApi { + getTree(): { + tree: AppTree; + }; +} + +// @public +export const appTreeApiRef: ApiRef; + // @public (undocumented) export interface BackstagePlugin< Routes extends AnyRoutes = AnyRoutes, diff --git a/packages/frontend-app-api/src/tree/types.ts b/packages/frontend-plugin-api/src/apis/definitions/AppTreeApi.ts similarity index 72% rename from packages/frontend-app-api/src/tree/types.ts rename to packages/frontend-plugin-api/src/apis/definitions/AppTreeApi.ts index 3246dfe5c2..6c79a16964 100644 --- a/packages/frontend-app-api/src/tree/types.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/AppTreeApi.ts @@ -14,20 +14,13 @@ * limitations under the License. */ -import { - BackstagePlugin, - Extension, - ExtensionDataRef, -} from '@backstage/frontend-plugin-api'; - -/* -NOTE: These types are marked as @internal for now, but the intention is for this to be a public API in the future. -*/ +import { createApiRef } from '@backstage/core-plugin-api'; +import { BackstagePlugin, Extension, ExtensionDataRef } from '../../wiring'; /** - * The specification for this node in the app tree. + * The specification for this {@link AppNode} in the {@link AppTree}. * - * @internal + * @public * @remarks * * The specifications for a collection of app nodes is all the information needed @@ -43,9 +36,9 @@ export interface AppNodeSpec { } /** - * The connections from this node to other nodes. + * The connections from this {@link AppNode} to other nodes. * - * @internal + * @public * @remarks * * The app node edges are resolved based on the app node specs, regardless of whether @@ -57,9 +50,9 @@ export interface AppNodeEdges { } /** - * The instance of this node in the app tree. + * The instance of this {@link AppNode} in the {@link AppTree}. * - * @internal + * @public * @remarks * * The app node instance is created when the `factory` function of an extension is called. @@ -74,8 +67,9 @@ export interface AppNodeInstance { } /** + * A node in the {@link AppTree}. * - * @internal + * @public */ export interface AppNode { /** The specification for how this node should be instantiated */ @@ -87,15 +81,34 @@ export interface AppNode { } /** - * The app tree containing all nodes of the app. + * The app tree containing all {@link AppNode}s of the app. * - * @internal + * @public */ export interface AppTree { /** The root node of the app */ - root: AppNode; + readonly root: AppNode; /** A map of all nodes in the app by ID, including orphaned or disabled nodes */ - nodes: ReadonlyMap; + readonly nodes: ReadonlyMap; /** A sequence of all nodes with a parent that is not reachable from the app root node */ - orphans: Iterable; + readonly orphans: Iterable; } + +/** + * The API for interacting with the {@link AppTree}. + * + * @public + */ +export interface AppTreeApi { + /** + * Get the {@link AppTree} for the app. + */ + getTree(): { tree: AppTree }; +} + +/** + * The `ApiRef` of {@link AppTreeApi}. + * + * @public + */ +export const appTreeApiRef = createApiRef({ id: 'core.app-tree' }); diff --git a/packages/frontend-plugin-api/src/apis/definitions/index.ts b/packages/frontend-plugin-api/src/apis/definitions/index.ts new file mode 100644 index 0000000000..8facdca2ca --- /dev/null +++ b/packages/frontend-plugin-api/src/apis/definitions/index.ts @@ -0,0 +1,25 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { + appTreeApiRef, + type AppNode, + type AppNodeEdges, + type AppNodeInstance, + type AppNodeSpec, + type AppTree, + type AppTreeApi, +} from './AppTreeApi'; diff --git a/packages/frontend-plugin-api/src/apis/index.ts b/packages/frontend-plugin-api/src/apis/index.ts new file mode 100644 index 0000000000..5a012c0553 --- /dev/null +++ b/packages/frontend-plugin-api/src/apis/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './definitions'; diff --git a/packages/frontend-plugin-api/src/index.ts b/packages/frontend-plugin-api/src/index.ts index 73abf28ce4..498bc96a77 100644 --- a/packages/frontend-plugin-api/src/index.ts +++ b/packages/frontend-plugin-api/src/index.ts @@ -20,6 +20,7 @@ * @packageDocumentation */ +export * from './apis'; export * from './components'; export * from './extensions'; export * from './routing'; diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index e8230f715e..4d5de74edb 100644 --- a/plugins/app-backend/package.json +++ b/plugins/app-backend/package.json @@ -57,7 +57,7 @@ "fs-extra": "10.1.0", "globby": "^11.0.0", "helmet": "^6.0.0", - "knex": "^2.0.0", + "knex": "^3.0.0", "lodash": "^4.17.21", "luxon": "^3.0.0", "winston": "^3.2.1", diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index b52560cbb9..52a4d262f7 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -51,7 +51,7 @@ "@types/express": "^4.17.6", "@types/passport": "^1.0.3", "compression": "^1.7.4", - "connect-session-knex": "^3.0.1", + "connect-session-knex": "^4.0.0", "cookie-parser": "^1.4.5", "cors": "^2.8.5", "express": "^4.17.1", @@ -61,7 +61,7 @@ "google-auth-library": "^8.0.0", "jose": "^4.6.0", "jwt-decode": "^3.1.0", - "knex": "^2.0.0", + "knex": "^3.0.0", "lodash": "^4.17.21", "luxon": "^3.0.0", "minimatch": "^5.0.0", diff --git a/plugins/badges-backend/package.json b/plugins/badges-backend/package.json index fee41b8e7f..21df60acb2 100644 --- a/plugins/badges-backend/package.json +++ b/plugins/badges-backend/package.json @@ -45,7 +45,7 @@ "cors": "^2.8.5", "express": "^4.17.1", "express-promise-router": "^4.1.0", - "knex": "^2.4.2", + "knex": "^3.0.0", "lodash": "^4.17.21", "supertest": "^6.3.3", "uuid": "^9.0.0", diff --git a/plugins/bazaar-backend/package.json b/plugins/bazaar-backend/package.json index 28489be39f..02ca87224b 100644 --- a/plugins/bazaar-backend/package.json +++ b/plugins/bazaar-backend/package.json @@ -49,7 +49,7 @@ "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", - "knex": "^2.0.0", + "knex": "^3.0.0", "winston": "^3.2.1", "yn": "^4.0.0" }, diff --git a/plugins/bazaar/README.md b/plugins/bazaar/README.md index 9b5fb466df..941979d4d3 100644 --- a/plugins/bazaar/README.md +++ b/plugins/bazaar/README.md @@ -2,15 +2,15 @@ ### What is the Bazaar? -The Bazaar is a place where teams can propose projects for cross-functional team development. Essentially a marketplace for internal projects suitable for [Inner Sourcing](https://en.wikipedia.org/wiki/Inner_source). With "Inner Sourcing", we mean projects that are developed internally within a company, but with Open Source best practices. +The Bazaar is a place where teams can propose projects for cross-functional team development. Essentially, it’s a marketplace for internal projects suitable for [Inner Sourcing](https://en.wikipedia.org/wiki/Inner_source). By “Inner Sourcing,” we mean projects that are developed internally within a company but follow Open Source best practices. ### Why? -Many companies today are of high need to increase the ease of cross-team cooperation. In large organizations, engineers often have limited ways of discovering or announcing the projects which could benefit from a wider development effort in terms of different expertise, experiences, and teams spread across the organization. With no good way to find these existing internal projects to join, the possibility of working with Inner Sourcing practices suffers. +Many companies today have a high need to increase the ease of cross-team cooperation. In large organizations, engineers often have limited ways of discovering or announcing projects that could benefit from a wider development effort in terms of different expertise, experiences, and teams spread across the organization. With no good way to find these existing internal projects to join, the possibility of working with Inner Sourcing practices suffers. ### How? -The Bazaar allows engineers and teams to open up and announce their new and exciting projects for transparent cooperation in other parts of larger organizations. The Bazaar ensures that new Inner Sourcing friendly projects gain visibility through Backstage and a way for interested engineers to show their interest and in the future contribute with their specific skill set. The Bazaar also provides an easy way to manage, catalog, and browse these Inner Sourcing friendly projects and components. +The Bazaar allows engineers and teams to open up and announce their new and exciting projects for transparent cooperation in other parts of larger organizations. The Bazaar ensures that new Inner Sourcing-friendly projects gain visibility through Backstage and a way for interested engineers to show their interest and, in the future, contribute with their specific skill set. The Bazaar also provides an easy way to manage, catalog, and browse these Inner Sourcing-friendly projects and components. # Note diff --git a/plugins/catalog-backend-module-gitlab/src/lib/client.ts b/plugins/catalog-backend-module-gitlab/src/lib/client.ts index c4cdd444cb..65c3898d06 100644 --- a/plugins/catalog-backend-module-gitlab/src/lib/client.ts +++ b/plugins/catalog-backend-module-gitlab/src/lib/client.ts @@ -92,7 +92,7 @@ export class GitLabClient { options?: CommonListOptions, ): Promise> { return this.pagedRequest( - `/groups/${encodeURIComponent(groupPath)}/members`, + `/groups/${encodeURIComponent(groupPath)}/members/all`, { ...options, show_seat_info: true, diff --git a/plugins/catalog-backend-module-gitlab/src/providers/GitlabOrgDiscoveryEntityProvider.test.ts b/plugins/catalog-backend-module-gitlab/src/providers/GitlabOrgDiscoveryEntityProvider.test.ts index ad930ea23d..669abc69b6 100644 --- a/plugins/catalog-backend-module-gitlab/src/providers/GitlabOrgDiscoveryEntityProvider.test.ts +++ b/plugins/catalog-backend-module-gitlab/src/providers/GitlabOrgDiscoveryEntityProvider.test.ts @@ -569,7 +569,7 @@ describe('GitlabOrgDiscoveryEntityProvider', () => { ), ), rest.get( - `https://gitlab.com/api/v4/groups/group1/members`, + `https://gitlab.com/api/v4/groups/group1/members/all`, (_req, res, ctx) => { const response = [ { diff --git a/plugins/catalog-backend-module-incremental-ingestion/package.json b/plugins/catalog-backend-module-incremental-ingestion/package.json index 5eb327b812..abe3de740e 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/package.json +++ b/plugins/catalog-backend-module-incremental-ingestion/package.json @@ -59,7 +59,7 @@ "@types/luxon": "^3.0.0", "express": "^4.17.1", "express-promise-router": "^4.1.0", - "knex": "^2.0.0", + "knex": "^3.0.0", "luxon": "^3.0.0", "uuid": "^8.3.2", "winston": "^3.2.1" diff --git a/plugins/catalog-backend-module-msgraph/api-report.md b/plugins/catalog-backend-module-msgraph/api-report.md index 3e4d8d99bc..7f5c4b804c 100644 --- a/plugins/catalog-backend-module-msgraph/api-report.md +++ b/plugins/catalog-backend-module-msgraph/api-report.md @@ -261,6 +261,17 @@ export function readMicrosoftGraphOrg( groups: GroupEntity[]; }>; +// @public +export function readProviderConfig( + id: string, + config: Config, +): MicrosoftGraphProviderConfig; + +// @public +export function readProviderConfigs( + config: Config, +): MicrosoftGraphProviderConfig[]; + // @public export type UserTransformer = ( user: MicrosoftGraph.User, diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.ts index cf4ec646a2..1d9592e96f 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.ts @@ -226,6 +226,13 @@ export function readMicrosoftGraphConfig( return providers; } +/** + * Parses all configured providers. + * + * @param config - The root of the msgraph config hierarchy + * + * @public + */ export function readProviderConfigs( config: Config, ): MicrosoftGraphProviderConfig[] { @@ -248,6 +255,14 @@ export function readProviderConfigs( }); } +/** + * Parses a single configured provider by id. + * + * @param id - the id of the provider to parse + * @param config - The root of the msgraph config hierarchy + * + * @public + */ export function readProviderConfig( id: string, config: Config, diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/index.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/index.ts index 37dcffec22..4db3fb69c6 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/index.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/index.ts @@ -16,7 +16,11 @@ export { MicrosoftGraphClient } from './client'; export type { GroupMember, ODataQuery } from './client'; -export { readMicrosoftGraphConfig } from './config'; +export { + readMicrosoftGraphConfig, + readProviderConfigs, + readProviderConfig, +} from './config'; export type { MicrosoftGraphProviderConfig } from './config'; export { MICROSOFT_EMAIL_ANNOTATION, diff --git a/plugins/catalog-backend-module-unprocessed/package.json b/plugins/catalog-backend-module-unprocessed/package.json index 03f3471b28..e04ce27b51 100644 --- a/plugins/catalog-backend-module-unprocessed/package.json +++ b/plugins/catalog-backend-module-unprocessed/package.json @@ -38,6 +38,6 @@ "@backstage/catalog-model": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", "express-promise-router": "^4.1.1", - "knex": "^2.4.2" + "knex": "^3.0.0" } } diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index a6f266af48..510312cc4c 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -71,7 +71,7 @@ "fs-extra": "10.1.0", "git-url-parse": "^13.0.0", "glob": "^7.1.6", - "knex": "^2.0.0", + "knex": "^3.0.0", "lodash": "^4.17.21", "luxon": "^3.0.0", "minimatch": "^5.0.0", @@ -93,7 +93,7 @@ "@types/lodash": "^4.14.151", "@types/supertest": "^2.0.8", "@types/uuid": "^8.0.0", - "better-sqlite3": "^8.0.0", + "better-sqlite3": "^9.0.0", "luxon": "^3.0.0", "msw": "^1.0.0", "supertest": "^6.1.3", diff --git a/plugins/catalog-react/api-report.md b/plugins/catalog-react/api-report.md index 03c97ee4c4..5ebc9de8d6 100644 --- a/plugins/catalog-react/api-report.md +++ b/plugins/catalog-react/api-report.md @@ -22,7 +22,7 @@ import { PropsWithChildren } from 'react'; import { default as React_2 } from 'react'; import { ReactNode } from 'react'; import { RouteRef } from '@backstage/core-plugin-api'; -import { ScmIntegrationRegistry } from '@backstage/integration'; +import { scmIntegrationsApiRef } from '@backstage/integration-react'; import { StyleRules } from '@material-ui/core/styles/withStyles'; import { SystemEntity } from '@backstage/catalog-model'; import { TableColumn } from '@backstage/core-components'; @@ -597,7 +597,7 @@ export function getEntityRelations( // @public (undocumented) export function getEntitySourceLocation( entity: Entity, - scmIntegrationsApi: ScmIntegrationRegistry, + scmIntegrationsApi: typeof scmIntegrationsApiRef.T, ): EntitySourceLocation | undefined; // @public (undocumented) diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index 25bd244ab7..3c39185732 100644 --- a/plugins/catalog-react/package.json +++ b/plugins/catalog-react/package.json @@ -52,7 +52,7 @@ "@backstage/core-plugin-api": "workspace:^", "@backstage/errors": "workspace:^", "@backstage/frontend-plugin-api": "workspace:^", - "@backstage/integration": "workspace:^", + "@backstage/integration-react": "workspace:^", "@backstage/plugin-catalog-common": "workspace:^", "@backstage/plugin-permission-common": "workspace:^", "@backstage/plugin-permission-react": "workspace:^", diff --git a/plugins/catalog-react/src/utils/getEntitySourceLocation.ts b/plugins/catalog-react/src/utils/getEntitySourceLocation.ts index d2141449a8..40074b79e2 100644 --- a/plugins/catalog-react/src/utils/getEntitySourceLocation.ts +++ b/plugins/catalog-react/src/utils/getEntitySourceLocation.ts @@ -19,7 +19,7 @@ import { Entity, parseLocationRef, } from '@backstage/catalog-model'; -import { ScmIntegrationRegistry } from '@backstage/integration'; +import { scmIntegrationsApiRef } from '@backstage/integration-react'; /** @public */ export type EntitySourceLocation = { @@ -30,7 +30,7 @@ export type EntitySourceLocation = { /** @public */ export function getEntitySourceLocation( entity: Entity, - scmIntegrationsApi: ScmIntegrationRegistry, + scmIntegrationsApi: typeof scmIntegrationsApiRef.T, ): EntitySourceLocation | undefined { const sourceLocation = entity.metadata.annotations?.[ANNOTATION_SOURCE_LOCATION]; diff --git a/plugins/catalog/src/components/EntityLayout/EntityLayout.test.tsx b/plugins/catalog/src/components/EntityLayout/EntityLayout.test.tsx index 33414152be..3634405af8 100644 --- a/plugins/catalog/src/components/EntityLayout/EntityLayout.test.tsx +++ b/plugins/catalog/src/components/EntityLayout/EntityLayout.test.tsx @@ -233,4 +233,35 @@ describe('EntityLayout', () => { expect(screen.queryByText('tabbed-test-title-2')).not.toBeInTheDocument(); expect(screen.getByText('tabbed-test-title-3')).toBeInTheDocument(); }); + + it('renders the owner links inside `p` tags', async () => { + const mockTargetRef = 'my:target/ref'; + const ownerEntity = { + ...mockEntity, + relations: [{ type: 'ownedBy', targetRef: mockTargetRef }], + }; + await renderInTestApp( + + + + +
tabbed-test-content
+
+
+
+
, + { + mountedRoutes: { + '/catalog/:namespace/:kind/:name': entityRouteRef, + }, + }, + ); + + const ownerLink = screen.getByText(mockTargetRef).closest('a'); + expect(ownerLink).toBeInTheDocument(); + expect(ownerLink?.tagName).toBe('A'); + const linkParent = ownerLink?.parentElement; + expect(linkParent).toBeInTheDocument(); + expect(linkParent?.tagName).toBe('P'); + }); }); diff --git a/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx b/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx index adad5d22af..fb6da04f1a 100644 --- a/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx +++ b/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx @@ -119,6 +119,7 @@ function EntityLabels(props: { entity: Entity }) { {ownedByRelations.length > 0 && ( ; + // (undocumented) + type: 'resourcequotas'; +} + // @public export interface ResourceRef { // (undocumented) diff --git a/plugins/kubernetes-common/src/types.ts b/plugins/kubernetes-common/src/types.ts index 9f8d5eed82..c9a4ce4c5a 100644 --- a/plugins/kubernetes-common/src/types.ts +++ b/plugins/kubernetes-common/src/types.ts @@ -27,6 +27,7 @@ import { V1LimitRange, V1Pod, V1ReplicaSet, + V1ResourceQuota, V1Service, V1StatefulSet, } from '@kubernetes/client-node'; @@ -125,6 +126,7 @@ export type FetchResponse = | ConfigMapFetchResponse | DeploymentFetchResponse | LimitRangeFetchResponse + | ResourceQuotaFetchResponse | ReplicaSetsFetchResponse | HorizontalPodAutoscalersFetchResponse | JobsFetchResponse @@ -171,6 +173,12 @@ export interface LimitRangeFetchResponse { resources: Array; } +/** @public */ +export interface ResourceQuotaFetchResponse { + type: 'resourcequotas'; + resources: Array; +} + /** @public */ export interface HorizontalPodAutoscalersFetchResponse { type: 'horizontalpodautoscalers'; diff --git a/plugins/linguist-backend/package.json b/plugins/linguist-backend/package.json index db00a9ecba..fad9bacc48 100644 --- a/plugins/linguist-backend/package.json +++ b/plugins/linguist-backend/package.json @@ -43,7 +43,7 @@ "express": "^4.18.1", "express-promise-router": "^4.1.0", "fs-extra": "^10.0.0", - "knex": "^2.0.0", + "knex": "^3.0.0", "linguist-js": "^2.5.3", "luxon": "^2.0.2", "node-fetch": "^2.6.7", diff --git a/plugins/playlist-backend/package.json b/plugins/playlist-backend/package.json index 17779c76fb..302f5f097a 100644 --- a/plugins/playlist-backend/package.json +++ b/plugins/playlist-backend/package.json @@ -41,7 +41,7 @@ "@types/express": "*", "express": "^4.17.1", "express-promise-router": "^4.1.0", - "knex": "^2.0.0", + "knex": "^3.0.0", "node-fetch": "^2.6.7", "uuid": "^8.2.0", "winston": "^3.2.1", diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 87493ab1a3..2630fa5e16 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -82,7 +82,7 @@ "isolated-vm": "^4.5.0", "isomorphic-git": "^1.23.0", "jsonschema": "^1.2.6", - "knex": "^2.0.0", + "knex": "^3.0.0", "libsodium-wrappers": "^0.7.11", "lodash": "^4.17.21", "luxon": "^3.0.0", diff --git a/plugins/search-backend-module-elasticsearch/api-report.md b/plugins/search-backend-module-elasticsearch/api-report.md index 408ec288d0..7de3a1857b 100644 --- a/plugins/search-backend-module-elasticsearch/api-report.md +++ b/plugins/search-backend-module-elasticsearch/api-report.md @@ -370,6 +370,7 @@ export type ElasticSearchSearchEngineIndexerOptions = { logger: Logger | LoggerService; elasticSearchClientWrapper: ElasticSearchClientWrapper; batchSize: number; + skipRefresh?: boolean; }; // @public (undocumented) diff --git a/plugins/search-backend-module-elasticsearch/config.d.ts b/plugins/search-backend-module-elasticsearch/config.d.ts index 95f1588fb4..b798240cef 100644 --- a/plugins/search-backend-module-elasticsearch/config.d.ts +++ b/plugins/search-backend-module-elasticsearch/config.d.ts @@ -115,6 +115,19 @@ export interface Config { * Eg. https://my-es-cluster.eu-west-1.es.amazonaws.com */ node: string; + + /** + * The AWS region. + * Only needed if using a custom DNS record. + */ + region?: string; + + /** + * The AWS service used for request signature. + * Either 'es' for "Managed Clusters" or 'aoss' for "Serverless". + * Only needed if using a custom DNS record. + */ + service?: 'es' | 'aoss'; } /** diff --git a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts index 9b085b52b0..8ccbe9a4ec 100644 --- a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts +++ b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts @@ -26,7 +26,10 @@ import { isEmpty, isNumber, isNaN as nan } from 'lodash'; import { AwsSigv4Signer } from '@opensearch-project/opensearch/aws'; import { RequestSigner } from 'aws4'; import { Config } from '@backstage/config'; -import { ElasticSearchClientOptions } from './ElasticSearchClientOptions'; +import { + ElasticSearchClientOptions, + OpenSearchElasticSearchClientOptions, +} from './ElasticSearchClientOptions'; import { ElasticSearchClientWrapper } from './ElasticSearchClientWrapper'; import { ElasticSearchCustomIndexTemplate } from './types'; import { ElasticSearchSearchEngineIndexer } from './ElasticSearchSearchEngineIndexer'; @@ -302,6 +305,11 @@ export class ElasticSearchSearchEngine implements SearchEngine { elasticSearchClientWrapper: this.elasticSearchClientWrapper, logger: indexerLogger, batchSize: this.batchSize, + skipRefresh: + ( + this + .elasticSearchClientOptions as OpenSearchElasticSearchClientOptions + )?.service === 'aoss', }); // Attempt cleanup upon failure. @@ -473,6 +481,8 @@ export class ElasticSearchSearchEngine implements SearchEngine { return { provider: 'aws', node: config.getString('node'), + region: config.getOptionalString('region'), + service, ...(sslConfig ? { ssl: { diff --git a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngineIndexer.test.ts b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngineIndexer.test.ts index 94b59fcf42..453a825574 100644 --- a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngineIndexer.test.ts +++ b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngineIndexer.test.ts @@ -34,6 +34,7 @@ describe('ElasticSearchSearchEngineIndexer', () => { let createSpy: jest.Mock; let aliasesSpy: jest.Mock; let deleteSpy: jest.Mock; + let refreshSpy: jest.Mock; beforeEach(() => { // Instantiate the indexer to be tested. @@ -45,6 +46,7 @@ describe('ElasticSearchSearchEngineIndexer', () => { logger: getVoidLogger(), elasticSearchClientWrapper: clientWrapper, batchSize: 1000, + skipRefresh: false, }); // Set up all requisite Elastic mocks. @@ -57,12 +59,13 @@ describe('ElasticSearchSearchEngineIndexer', () => { }, bulkSpy, ); + refreshSpy = jest.fn().mockReturnValue({}); mock.add( { method: 'GET', path: '/:index/_refresh', }, - jest.fn().mockReturnValue({}), + refreshSpy, ); catSpy = jest.fn().mockReturnValue([ @@ -212,6 +215,7 @@ describe('ElasticSearchSearchEngineIndexer', () => { // Ensure multiple bulk requests were made. expect(bulkSpy).toHaveBeenCalledTimes(2); + expect(refreshSpy).toHaveBeenCalledTimes(1); // Ensure the first and last documents were included in the payloads. const docLocations: string[] = [ @@ -269,6 +273,7 @@ describe('ElasticSearchSearchEngineIndexer', () => { logger: getVoidLogger(), elasticSearchClientWrapper: mockClientWrapper, batchSize: 1000, + skipRefresh: false, }); // When the indexer is run in the test pipeline @@ -279,4 +284,37 @@ describe('ElasticSearchSearchEngineIndexer', () => { // Then the pipeline should have received the expected error expect(error).toBe(expectedError); }); + + it('indexes documents, skip refresh', async () => { + // Instantiate the indexer to be tested. + indexer = new ElasticSearchSearchEngineIndexer({ + type: 'some-type', + indexPrefix: '', + indexSeparator: '-index__', + alias: 'some-type-index__search', + logger: getVoidLogger(), + elasticSearchClientWrapper: clientWrapper, + batchSize: 1000, + skipRefresh: true, + }); + + const documents = [ + { + title: 'testTerm', + text: 'testText', + location: 'test/location', + }, + { + title: 'Another test', + text: 'Some more text', + location: 'test/location/2', + }, + ]; + + await TestPipeline.fromIndexer(indexer).withDocuments(documents).execute(); + + // Ensure bulk called but refresh not + expect(bulkSpy).toHaveBeenCalledTimes(1); + expect(refreshSpy).toHaveBeenCalledTimes(0); + }); }); diff --git a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngineIndexer.ts b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngineIndexer.ts index b742216d52..4b1307114a 100644 --- a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngineIndexer.ts +++ b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngineIndexer.ts @@ -33,6 +33,7 @@ export type ElasticSearchSearchEngineIndexerOptions = { logger: Logger | LoggerService; elasticSearchClientWrapper: ElasticSearchClientWrapper; batchSize: number; + skipRefresh?: boolean; }; function duration(startTimestamp: [number, number]): string { @@ -95,7 +96,7 @@ export class ElasticSearchSearchEngineIndexer extends BatchSearchEngineIndexer { index: { _index: that.indexName }, }; }, - refreshOnCompletion: that.indexName, + refreshOnCompletion: options.skipRefresh !== true, }); // Safely catch errors thrown by the bulk helper client, e.g. HTTP timeouts diff --git a/plugins/search-backend-module-pg/package.json b/plugins/search-backend-module-pg/package.json index cda72a9008..5669458bb3 100644 --- a/plugins/search-backend-module-pg/package.json +++ b/plugins/search-backend-module-pg/package.json @@ -47,7 +47,7 @@ "@backstage/config": "workspace:^", "@backstage/plugin-search-backend-node": "workspace:^", "@backstage/plugin-search-common": "workspace:^", - "knex": "^2.0.0", + "knex": "^3.0.0", "lodash": "^4.17.21", "uuid": "^8.3.2", "winston": "^3.2.1" diff --git a/plugins/shortcuts/src/ShortcutForm.tsx b/plugins/shortcuts/src/ShortcutForm.tsx index e8cd8144d0..4d6fdcbc27 100644 --- a/plugins/shortcuts/src/ShortcutForm.tsx +++ b/plugins/shortcuts/src/ShortcutForm.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import React, { useEffect } from 'react'; +import React, { useEffect, useRef } from 'react'; import useObservable from 'react-use/lib/useObservable'; import { useForm, SubmitHandler, Controller } from 'react-hook-form'; import { @@ -58,6 +58,10 @@ export const ShortcutForm = ({ shortcutApi.shortcut$(), shortcutApi.get(), ); + const { current: originalValues } = useRef({ + url: formValues?.url ?? '', + title: formValues?.title ?? '', + }); const { handleSubmit, reset, @@ -65,20 +69,23 @@ export const ShortcutForm = ({ formState: { errors }, } = useForm({ mode: 'onChange', - defaultValues: { - url: formValues?.url ?? '', - title: formValues?.title ?? '', - }, + defaultValues: originalValues, }); const titleIsUnique = (title: string) => { - if (shortcutData.some(shortcutTitle => shortcutTitle.title === title)) + if ( + title !== originalValues.title && + shortcutData.some(shortcutTitle => shortcutTitle.title === title) + ) return 'A shortcut with this title already exists'; return true; }; const urlIsUnique = (url: string) => { - if (shortcutData.some(shortcutUrl => shortcutUrl.url === url)) + if ( + url !== originalValues.url && + shortcutData.some(shortcutUrl => shortcutUrl.url === url) + ) return 'A shortcut with this url already exists'; return true; }; diff --git a/plugins/tech-insights-backend/package.json b/plugins/tech-insights-backend/package.json index a681601637..842a8db339 100644 --- a/plugins/tech-insights-backend/package.json +++ b/plugins/tech-insights-backend/package.json @@ -46,7 +46,7 @@ "@types/luxon": "^3.0.0", "express": "^4.17.1", "express-promise-router": "^4.1.0", - "knex": "^2.0.0", + "knex": "^3.0.0", "lodash": "^4.17.21", "luxon": "^3.0.0", "semver": "^7.5.3", diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json index 8b87f455f1..566538fde6 100644 --- a/plugins/techdocs-backend/package.json +++ b/plugins/techdocs-backend/package.json @@ -63,7 +63,7 @@ "express": "^4.17.1", "express-promise-router": "^4.1.0", "fs-extra": "10.1.0", - "knex": "^2.0.0", + "knex": "^3.0.0", "lodash": "^4.17.21", "node-fetch": "^2.6.7", "p-limit": "^3.1.0", diff --git a/plugins/user-settings-backend/package.json b/plugins/user-settings-backend/package.json index 0184cf75ef..3a560bfdbb 100644 --- a/plugins/user-settings-backend/package.json +++ b/plugins/user-settings-backend/package.json @@ -52,7 +52,7 @@ "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", - "knex": "^2.0.0", + "knex": "^3.0.0", "winston": "^3.2.1", "yn": "^4.0.0" }, diff --git a/yarn.lock b/yarn.lock index f98a71a3b1..fb2a86c753 100644 --- a/yarn.lock +++ b/yarn.lock @@ -115,8 +115,8 @@ __metadata: linkType: hard "@apollo/client@npm:^3.0.0": - version: 3.8.6 - resolution: "@apollo/client@npm:3.8.6" + version: 3.8.7 + resolution: "@apollo/client@npm:3.8.7" dependencies: "@graphql-typed-document-node/core": ^3.1.1 "@wry/context": ^0.7.3 @@ -146,7 +146,7 @@ __metadata: optional: true subscriptions-transport-ws: optional: true - checksum: 34a917d3456c1f728834eaaee00a98f82c7f60de8e0e0c62154667f7e95a635740a2d43fe43f51f85950eb2abe06a3d326f32393a48dd4afc6e4fb4357876dc1 + checksum: b4343d7f64481d6e4ee9f3ff461cfdab669728104b7540a4fff885232335fed55920e76de823ee4f2fa711aa72afbbf1cfe29601eacabb3577dc1f3ee82046d4 languageName: node linkType: hard @@ -212,8 +212,8 @@ __metadata: linkType: hard "@apollo/server@npm:^4.0.0": - version: 4.9.4 - resolution: "@apollo/server@npm:4.9.4" + version: 4.9.5 + resolution: "@apollo/server@npm:4.9.5" dependencies: "@apollo/cache-control-types": ^1.0.3 "@apollo/server-gateway-interface": ^1.1.1 @@ -243,7 +243,7 @@ __metadata: whatwg-mimetype: ^3.0.0 peerDependencies: graphql: ^16.6.0 - checksum: bf7105ffceaed6e3c54f1506513944bb324ae32e92b1aabb3ec7de1b9fee1373bdec6e1a3f5efb7c7f8090671f1ba2d37c01f5b1456c93127ffede1a0b554bac + checksum: 52aac2ef0665a776b2da8930b2a6e31b652a9a3c5b2e48e56d323e40b618acae091c69dc04ebed5355a36e22b793ceb31baa04afe516205c67c2db87c0fb01a0 languageName: node linkType: hard @@ -1735,8 +1735,8 @@ __metadata: linkType: hard "@azure/identity@npm:^3.2.1": - version: 3.3.1 - resolution: "@azure/identity@npm:3.3.1" + version: 3.3.2 + resolution: "@azure/identity@npm:3.3.2" dependencies: "@azure/abort-controller": ^1.0.0 "@azure/core-auth": ^1.5.0 @@ -1754,7 +1754,7 @@ __metadata: stoppable: ^1.1.0 tslib: ^2.2.0 uuid: ^8.3.0 - checksum: ba58ce8d6178566757c0554b9b5d6ca3d4e934eb6831c9a7d57ada185ec57bd9a9de1ce9500a547e35f4d11cfb362c312afaad019d1ed6bf7b6ebf908bfea362 + checksum: 53a650dc6f73fb35137fd4e35f6db8b04bb77b3b8598f4fa5cc145e79ba1c28258bea535fb0af7f09d7fec4b44bbda0a1a3a2b593c6d8e576e23022617c8611e languageName: node linkType: hard @@ -1863,26 +1863,26 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.13.16, @babel/core@npm:^7.14.0, @babel/core@npm:^7.19.6, @babel/core@npm:^7.22.20": - version: 7.23.0 - resolution: "@babel/core@npm:7.23.0" +"@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.13.16, @babel/core@npm:^7.14.0, @babel/core@npm:^7.19.6, @babel/core@npm:^7.23.2": + version: 7.23.2 + resolution: "@babel/core@npm:7.23.2" dependencies: "@ampproject/remapping": ^2.2.0 "@babel/code-frame": ^7.22.13 "@babel/generator": ^7.23.0 "@babel/helper-compilation-targets": ^7.22.15 "@babel/helper-module-transforms": ^7.23.0 - "@babel/helpers": ^7.23.0 + "@babel/helpers": ^7.23.2 "@babel/parser": ^7.23.0 "@babel/template": ^7.22.15 - "@babel/traverse": ^7.23.0 + "@babel/traverse": ^7.23.2 "@babel/types": ^7.23.0 convert-source-map: ^2.0.0 debug: ^4.1.0 gensync: ^1.0.0-beta.2 json5: ^2.2.3 semver: ^6.3.1 - checksum: cebd9b48dbc970a7548522f207f245c69567e5ea17ebb1a4e4de563823cf20a01177fe8d2fe19b6e1461361f92fa169fd0b29f8ee9d44eeec84842be1feee5f2 + checksum: 003897718ded16f3b75632d63cd49486bf67ff206cc7ebd1a10d49e2456f8d45740910d5ec7e42e3faf0deec7a2e96b1a02e766d19a67a8309053f0d4e57c0fe languageName: node linkType: hard @@ -2136,14 +2136,14 @@ __metadata: languageName: node linkType: hard -"@babel/helpers@npm:^7.23.0": - version: 7.23.1 - resolution: "@babel/helpers@npm:7.23.1" +"@babel/helpers@npm:^7.23.2": + version: 7.23.2 + resolution: "@babel/helpers@npm:7.23.2" dependencies: "@babel/template": ^7.22.15 - "@babel/traverse": ^7.23.0 + "@babel/traverse": ^7.23.2 "@babel/types": ^7.23.0 - checksum: acfc345102045c24ea2a4d60e00dcf8220e215af3add4520e2167700661338e6a80bd56baf44bb764af05ec6621101c9afc315dc107e18c61fa6da8acbdbb893 + checksum: aaf4828df75ec460eaa70e5c9f66e6dadc28dae3728ddb7f6c13187dbf38030e142194b83d81aa8a31bbc35a5529a5d7d3f3cf59d5d0b595f5dd7f9d8f1ced8e languageName: node linkType: hard @@ -3393,9 +3393,9 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.14.0, @babel/traverse@npm:^7.16.8, @babel/traverse@npm:^7.23.0, @babel/traverse@npm:^7.4.5": - version: 7.23.0 - resolution: "@babel/traverse@npm:7.23.0" +"@babel/traverse@npm:^7.14.0, @babel/traverse@npm:^7.16.8, @babel/traverse@npm:^7.23.2, @babel/traverse@npm:^7.4.5": + version: 7.23.2 + resolution: "@babel/traverse@npm:7.23.2" dependencies: "@babel/code-frame": ^7.22.13 "@babel/generator": ^7.23.0 @@ -3407,7 +3407,7 @@ __metadata: "@babel/types": ^7.23.0 debug: ^4.1.0 globals: ^11.1.0 - checksum: 0b17fae53269e1af2cd3edba00892bc2975ad5df9eea7b84815dab07dfec2928c451066d51bc65b4be61d8499e77db7e547ce69ef2a7b0eca3f96269cb43a0b0 + checksum: 26a1eea0dde41ab99dde8b9773a013a0dc50324e5110a049f5d634e721ff08afffd54940b3974a20308d7952085ac769689369e9127dea655f868c0f6e1ab35d languageName: node linkType: hard @@ -3538,7 +3538,7 @@ __metadata: archiver: ^5.0.2 aws-sdk-client-mock: ^2.0.0 base64-stream: ^1.0.0 - better-sqlite3: ^8.0.0 + better-sqlite3: ^9.0.0 compression: ^1.7.4 concat-stream: ^2.0.0 cors: ^2.8.5 @@ -3552,7 +3552,7 @@ __metadata: isomorphic-git: ^1.23.0 jose: ^4.6.0 keyv: ^4.5.2 - knex: ^2.0.0 + knex: ^3.0.0 lodash: ^4.17.21 logform: ^2.3.2 luxon: ^3.0.0 @@ -3560,7 +3560,7 @@ __metadata: msw: ^1.0.0 mysql2: ^2.2.5 node-fetch: ^2.6.7 - pg: ^8.3.0 + pg: ^8.11.3 raw-body: ^2.4.1 supertest: ^6.1.3 tar: ^6.1.12 @@ -3630,7 +3630,7 @@ __metadata: "@backstage/types": "workspace:^" "@types/express": ^4.17.6 express: ^4.17.1 - knex: ^2.0.0 + knex: ^3.0.0 languageName: unknown linkType: soft @@ -3682,7 +3682,7 @@ __metadata: "@types/cron": ^2.0.0 "@types/luxon": ^3.0.0 cron: ^2.0.0 - knex: ^2.0.0 + knex: ^3.0.0 lodash: ^4.17.21 luxon: ^3.0.0 uuid: ^8.0.0 @@ -3705,13 +3705,13 @@ __metadata: "@backstage/plugin-auth-node": "workspace:^" "@backstage/types": "workspace:^" "@types/supertest": ^2.0.8 - better-sqlite3: ^8.0.0 + better-sqlite3: ^9.0.0 express: ^4.17.1 fs-extra: ^10.0.1 - knex: ^2.0.0 + knex: ^3.0.0 msw: ^1.0.0 mysql2: ^2.2.5 - pg: ^8.3.0 + pg: ^8.11.3 supertest: ^6.1.3 testcontainers: ^8.1.2 textextensions: ^5.16.0 @@ -4889,7 +4889,7 @@ __metadata: fs-extra: 10.1.0 globby: ^11.0.0 helmet: ^6.0.0 - knex: ^2.0.0 + knex: ^3.0.0 lodash: ^4.17.21 luxon: ^3.0.0 msw: ^1.0.0 @@ -5076,7 +5076,7 @@ __metadata: "@types/passport-strategy": ^0.2.35 "@types/xml2js": ^0.4.7 compression: ^1.7.4 - connect-session-knex: ^3.0.1 + connect-session-knex: ^4.0.0 cookie-parser: ^1.4.5 cors: ^2.8.5 express: ^4.17.1 @@ -5086,7 +5086,7 @@ __metadata: google-auth-library: ^8.0.0 jose: ^4.6.0 jwt-decode: ^3.1.0 - knex: ^2.0.0 + knex: ^3.0.0 lodash: ^4.17.21 luxon: ^3.0.0 minimatch: ^5.0.0 @@ -5289,7 +5289,7 @@ __metadata: cross-fetch: ^3.1.5 express: ^4.17.1 express-promise-router: ^4.1.0 - knex: ^2.4.2 + knex: ^3.0.0 lodash: ^4.17.21 supertest: ^6.3.3 uuid: ^9.0.0 @@ -5339,7 +5339,7 @@ __metadata: "@types/express": ^4.17.6 express: ^4.17.1 express-promise-router: ^4.1.0 - knex: ^2.0.0 + knex: ^3.0.0 winston: ^3.2.1 yn: ^4.0.0 languageName: unknown @@ -5720,7 +5720,7 @@ __metadata: "@types/luxon": ^3.0.0 express: ^4.17.1 express-promise-router: ^4.1.0 - knex: ^2.0.0 + knex: ^3.0.0 luxon: ^3.0.0 uuid: ^8.3.2 winston: ^3.2.1 @@ -5845,7 +5845,7 @@ __metadata: "@backstage/cli": "workspace:^" "@backstage/plugin-auth-node": "workspace:^" express-promise-router: ^4.1.1 - knex: ^2.4.2 + knex: ^3.0.0 languageName: unknown linkType: soft @@ -5879,7 +5879,7 @@ __metadata: "@types/lodash": ^4.14.151 "@types/supertest": ^2.0.8 "@types/uuid": ^8.0.0 - better-sqlite3: ^8.0.0 + better-sqlite3: ^9.0.0 codeowners-utils: ^1.0.2 core-js: ^3.6.5 express: ^4.17.1 @@ -5887,7 +5887,7 @@ __metadata: fs-extra: 10.1.0 git-url-parse: ^13.0.0 glob: ^7.1.6 - knex: ^2.0.0 + knex: ^3.0.0 lodash: ^4.17.21 luxon: ^3.0.0 minimatch: ^5.0.0 @@ -6089,7 +6089,7 @@ __metadata: "@backstage/core-plugin-api": "workspace:^" "@backstage/errors": "workspace:^" "@backstage/frontend-plugin-api": "workspace:^" - "@backstage/integration": "workspace:^" + "@backstage/integration-react": "workspace:^" "@backstage/plugin-catalog-common": "workspace:^" "@backstage/plugin-permission-common": "workspace:^" "@backstage/plugin-permission-react": "workspace:^" @@ -6367,7 +6367,7 @@ __metadata: body-parser-xml: ^2.0.5 express: ^4.17.1 express-promise-router: ^4.1.0 - knex: ^2.0.0 + knex: ^3.0.0 msw: ^1.0.0 supertest: ^6.1.6 uuid: ^8.3.2 @@ -6663,7 +6663,7 @@ __metadata: "@types/supertest": ^2.0.12 express: ^4.18.1 express-promise-router: ^4.1.0 - knex: ^2.0.0 + knex: ^3.0.0 msw: ^1.0.0 node-fetch: ^2.6.7 supertest: ^6.2.4 @@ -7984,7 +7984,7 @@ __metadata: express-promise-router: ^4.1.0 fs-extra: ^10.0.0 js-yaml: ^4.1.0 - knex: ^2.0.0 + knex: ^3.0.0 linguist-js: ^2.5.3 luxon: ^2.0.2 msw: ^1.0.0 @@ -8544,7 +8544,7 @@ __metadata: "@types/supertest": ^2.0.8 express: ^4.17.1 express-promise-router: ^4.1.0 - knex: ^2.0.0 + knex: ^3.0.0 msw: ^1.0.0 node-fetch: ^2.6.7 supertest: ^6.1.3 @@ -8881,7 +8881,7 @@ __metadata: isomorphic-git: ^1.23.0 jest-when: ^3.1.0 jsonschema: ^1.2.6 - knex: ^2.0.0 + knex: ^3.0.0 libsodium-wrappers: ^0.7.11 lodash: ^4.17.21 luxon: ^3.0.0 @@ -9133,7 +9133,7 @@ __metadata: "@backstage/config": "workspace:^" "@backstage/plugin-search-backend-node": "workspace:^" "@backstage/plugin-search-common": "workspace:^" - knex: ^2.0.0 + knex: ^3.0.0 lodash: ^4.17.21 uuid: ^8.3.2 winston: ^3.2.1 @@ -9614,7 +9614,7 @@ __metadata: "@types/supertest": ^2.0.8 express: ^4.17.1 express-promise-router: ^4.1.0 - knex: ^2.0.0 + knex: ^3.0.0 lodash: ^4.17.21 luxon: ^3.0.0 semver: ^7.5.3 @@ -9780,7 +9780,7 @@ __metadata: express: ^4.17.1 express-promise-router: ^4.1.0 fs-extra: 10.1.0 - knex: ^2.0.0 + knex: ^3.0.0 lodash: ^4.17.21 msw: ^1.0.0 node-fetch: ^2.6.7 @@ -10022,7 +10022,7 @@ __metadata: "@types/supertest": ^2.0.8 express: ^4.17.1 express-promise-router: ^4.1.0 - knex: ^2.0.0 + knex: ^3.0.0 supertest: ^6.1.3 winston: ^3.2.1 yn: ^4.0.0 @@ -10631,8 +10631,8 @@ __metadata: linkType: hard "@codemirror/language@npm:^6.0.0": - version: 6.9.1 - resolution: "@codemirror/language@npm:6.9.1" + version: 6.9.2 + resolution: "@codemirror/language@npm:6.9.2" dependencies: "@codemirror/state": ^6.0.0 "@codemirror/view": ^6.0.0 @@ -10640,7 +10640,7 @@ __metadata: "@lezer/highlight": ^1.0.0 "@lezer/lr": ^1.0.0 style-mod: ^4.0.0 - checksum: 62265f1042d2edfd3a091c408d9d0071f23889099b2f6ce8275fa910118bd2c45b8c4b29228c7be6e6d5f0e0812a522de902bc75ba8d8b2e62e42ade1692a49a + checksum: eee7b861b5591114cac7502cd532d5b923639740081a4cd7e28696c252af8d759b14686aaf6d5eee7e0969ff647b7aaf03a5eea7235fb6d9858ee19433f1c74d languageName: node linkType: hard @@ -10695,13 +10695,13 @@ __metadata: linkType: hard "@codemirror/view@npm:^6.0.0": - version: 6.21.3 - resolution: "@codemirror/view@npm:6.21.3" + version: 6.22.0 + resolution: "@codemirror/view@npm:6.22.0" dependencies: "@codemirror/state": ^6.1.4 style-mod: ^4.1.0 w3c-keyname: ^2.2.4 - checksum: 7fda5a60e04fe1ac3d22ee478d4a90fc307953b8c900752ef5ca33af06c4e7851356e460f14b05034230b3a1677f36379ea01d85a3ea3b3a3e85e871ed62346a + checksum: 2a24674687fbde06898d0a131abe5f86a812d79e111cf8dc94110dac86eed8c20a2094b547c1b3c379fe8edf0c66318d03a7594158e4f6628ee060a03a5d1bab languageName: node linkType: hard @@ -14146,6 +14146,19 @@ __metadata: languageName: node linkType: hard +"@npmcli/agent@npm:^2.0.0": + version: 2.2.0 + resolution: "@npmcli/agent@npm:2.2.0" + dependencies: + agent-base: ^7.1.0 + http-proxy-agent: ^7.0.0 + https-proxy-agent: ^7.0.1 + lru-cache: ^10.0.1 + socks-proxy-agent: ^8.0.1 + checksum: 3b25312edbdfaa4089af28e2d423b6f19838b945e47765b0c8174c1395c79d43c3ad6d23cb364b43f59fd3acb02c93e3b493f72ddbe3dfea04c86843a7311fc4 + languageName: node + linkType: hard + "@npmcli/arborist@npm:^4.0.4": version: 4.3.1 resolution: "@npmcli/arborist@npm:4.3.1" @@ -18118,16 +18131,16 @@ __metadata: languageName: node linkType: hard -"@types/babel__core@npm:^7.1.14, @types/babel__core@npm:^7.20.2": - version: 7.20.2 - resolution: "@types/babel__core@npm:7.20.2" +"@types/babel__core@npm:^7.1.14, @types/babel__core@npm:^7.20.3": + version: 7.20.3 + resolution: "@types/babel__core@npm:7.20.3" dependencies: "@babel/parser": ^7.20.7 "@babel/types": ^7.20.7 "@types/babel__generator": "*" "@types/babel__template": "*" "@types/babel__traverse": "*" - checksum: 564fbaa8ff1305d50807ada0ec227c3e7528bebb2f8fe6b2ed88db0735a31511a74ad18729679c43eeed8025ed29d408f53059289719e95ab1352ed559a100bd + checksum: 8d14acc14d99b4b8bf36c00da368f6d597bd9ae3344aa7048f83f0f701b0463fa7c7bf2e50c3e4382fdbcfd1e4187b3452a0f0888b0f3ae8fad975591f7bdb94 languageName: node linkType: hard @@ -18362,11 +18375,11 @@ __metadata: linkType: hard "@types/cors@npm:^2.8.6": - version: 2.8.14 - resolution: "@types/cors@npm:2.8.14" + version: 2.8.15 + resolution: "@types/cors@npm:2.8.15" dependencies: "@types/node": "*" - checksum: 119b8ea5760db58542cc66635e8b98b9e859d615e9fc7bfd520c0e2c94063e87759033a4242360e2aa66df2d7d092a406838ac35e8ca7034debf1c69abc27811 + checksum: ef7b0aba4c6a4c1fe9d459bd471ebaa891a75319682c9248daa17720003d1d0d2c59de4bdb6868630596ade9b7c3c949e652d6141b14c6fe4387ffcc520d0f3f languageName: node linkType: hard @@ -18418,9 +18431,9 @@ __metadata: linkType: hard "@types/d3-force@npm:^3.0.0": - version: 3.0.7 - resolution: "@types/d3-force@npm:3.0.7" - checksum: fd846e5d79dabd8d375b68c64cd218b4867e229eb6cb584b302ed9b96105cb267300fee63b0cd762417c28168d0a64047b7e6eff2acc8b5c561fded74f86fa8c + version: 3.0.8 + resolution: "@types/d3-force@npm:3.0.8" + checksum: cac7404f1b94a1eb8b17690481e1f16228582d297dc609147aa2b32c2c14cb4bf8b06be10d375b6a863da237968d8c441d2d0f73054b4cca717f3f4b7c5185af languageName: node linkType: hard @@ -18457,9 +18470,9 @@ __metadata: linkType: hard "@types/d3-selection@npm:*, @types/d3-selection@npm:^3.0.1": - version: 3.0.8 - resolution: "@types/d3-selection@npm:3.0.8" - checksum: 5655584116a97876d22c68387551d6e029d306894ca15c5b71635c2cc528288bddee67799ae2c677b028f2f26f99fcc8d598e47f5a67d5c1e3dd9b5507771f90 + version: 3.0.9 + resolution: "@types/d3-selection@npm:3.0.9" + checksum: 1f9c0456e2eb8255cfd03df9628705309a2d4889faed51115b8fd429ddf168a2eee32e9dfbb26cf31cf2f9409e213146ab5d0c7d2479996e40980da97f144d5a languageName: node linkType: hard @@ -18496,12 +18509,12 @@ __metadata: linkType: hard "@types/d3-zoom@npm:^3.0.1": - version: 3.0.6 - resolution: "@types/d3-zoom@npm:3.0.6" + version: 3.0.7 + resolution: "@types/d3-zoom@npm:3.0.7" dependencies: "@types/d3-interpolate": "*" "@types/d3-selection": "*" - checksum: 6b0ad10b6a7bab3acfdc92b0cd34c74698305a71e2fefb20eae1e3bac95cbf70c6434be5ea2c1c71bbe9fcb134c66da44fdd75673437199e9a90aea8aea0f7e7 + checksum: 770bad9e1878a4461708c2507305d2ae45534293a73ebce7bcd48ede0a889588ceb66057dc68dc570cabd8eba338853d304a458452109dffc425fd087e7d36c2 languageName: node linkType: hard @@ -18539,12 +18552,12 @@ __metadata: linkType: hard "@types/dockerode@npm:^3.3.0, @types/dockerode@npm:^3.3.8": - version: 3.3.21 - resolution: "@types/dockerode@npm:3.3.21" + version: 3.3.22 + resolution: "@types/dockerode@npm:3.3.22" dependencies: "@types/docker-modem": "*" "@types/node": "*" - checksum: 025c97cd2549f1b3f0dc6e117e24e3b7e56dcf3e482e2abe5f2d6961e56e637b0e1f1b4f032e065cd7245302064ac3ccdb9c7dfdb0fe43a5bfb2b5f4ccbf4a8d + checksum: e9954730eea82a87e21dd5322ac090b389e3294d646f27785dc553496435146ecd828102250a31bad94f81a8ca292b0fd2e061675b00f2b93f6191d2615a839e languageName: node linkType: hard @@ -18622,14 +18635,14 @@ __metadata: linkType: hard "@types/express-serve-static-core@npm:*, @types/express-serve-static-core@npm:^4.17.30, @types/express-serve-static-core@npm:^4.17.33, @types/express-serve-static-core@npm:^4.17.5": - version: 4.17.39 - resolution: "@types/express-serve-static-core@npm:4.17.39" + version: 4.17.40 + resolution: "@types/express-serve-static-core@npm:4.17.40" dependencies: "@types/node": "*" "@types/qs": "*" "@types/range-parser": "*" "@types/send": "*" - checksum: 4227b96a53f0cf19d01fdb77a74252660f8e70650b79167e591b04c66ec9c7330d0a00038939415f96664a67312b21798bbac150fe81bf613380849b96546c37 + checksum: cf64bc1eb5625c2940175f3e9d62bb0b9e3ec08f9ecd8cc913c4e3f52191ab07d3b2b290cb420f435a1464e54ecf5ea6fd8486e02b22baa749bd0a942b31432b languageName: node linkType: hard @@ -18849,12 +18862,12 @@ __metadata: linkType: hard "@types/jest@npm:*, @types/jest@npm:^29.0.0": - version: 29.5.6 - resolution: "@types/jest@npm:29.5.6" + version: 29.5.7 + resolution: "@types/jest@npm:29.5.7" dependencies: expect: ^29.0.0 pretty-format: ^29.0.0 - checksum: fa13a27bd1c8efd0381a419478769d0d6d3a8e93e1952d7ac3a16274e8440af6f73ed6f96ac1ff00761198badf2ee226b5ab5583a5d87a78d609ea78da5c5a24 + checksum: e28624ccb0ef1255a03fbbb4b5bc3e5cbcdc450d39e0739985ff679b124198f808c38c8c3e67859c6efc0e848196deeb8cfed028e12a821c511dfc1112a2d6e9 languageName: node linkType: hard @@ -18869,11 +18882,11 @@ __metadata: linkType: hard "@types/jquery@npm:^3.3.34": - version: 3.5.25 - resolution: "@types/jquery@npm:3.5.25" + version: 3.5.26 + resolution: "@types/jquery@npm:3.5.26" dependencies: "@types/sizzle": "*" - checksum: 912ce4212447a7c640147345c6b46bde5b12bafc2c97e1abc76939174c3109e3dbb361a534af717be2da4e907bc257558a6bc631971fcc47f7e5f044d315183e + checksum: 4c46902939d35a791a798f44567ef485d7aacf709a93e6f18d3fe4060c79183829b12050c53576014c4e25ee7bfd42e545e6b9c721a28f3e9d53e24d46653b3c languageName: node linkType: hard @@ -19124,11 +19137,11 @@ __metadata: linkType: hard "@types/morgan@npm:^1.9.0": - version: 1.9.7 - resolution: "@types/morgan@npm:1.9.7" + version: 1.9.8 + resolution: "@types/morgan@npm:1.9.8" dependencies: "@types/node": "*" - checksum: 3e66ad27bd0ec599981c13bc0425957be861dcb7a31ec464ce01ef98daae828092dbb8250758aeed65c5b28a4ebd449b0baa51064c0611b0e2c8358e2c27cae2 + checksum: ce088ea27be590db6620ebc55864a72f577ff7a1bf01b7557ba070680c44be536e3fe7704493781e6d8b3af9363acfc9e3c0f917ae437631133ee4b49cd4ac0a languageName: node linkType: hard @@ -19178,11 +19191,11 @@ __metadata: linkType: hard "@types/node@npm:*, @types/node@npm:>=12.12.47, @types/node@npm:>=13.7.0, @types/node@npm:^20.1.1": - version: 20.8.6 - resolution: "@types/node@npm:20.8.6" + version: 20.8.10 + resolution: "@types/node@npm:20.8.10" dependencies: - undici-types: ~5.25.1 - checksum: ccfb7ac482c5a96edeb239893c5c099f5257fcc2ed9ae62fefdfbc782b79e16dbc2af9a85b379665237bf759904b44ca2be68e75d239e0297882aad42f61905c + undici-types: ~5.26.4 + checksum: 7c61190e43e8074a1b571e52ff14c880bc67a0447f2fe5ed0e1a023eb8a23d5f815658edb98890f7578afe0f090433c4a635c7c87311762544e20dd78723e515 languageName: node linkType: hard @@ -19201,9 +19214,9 @@ __metadata: linkType: hard "@types/node@npm:^16.11.26, @types/node@npm:^16.7.10, @types/node@npm:^16.9.2": - version: 16.18.59 - resolution: "@types/node@npm:16.18.59" - checksum: 70f28744d239c48db056ff6355d2eb99305db54d1f9377b3f4458e92ffb4da8962a0c67665452d5f430cea2286ced256dac8f769660007aedd3676cf03ff28ad + version: 16.18.60 + resolution: "@types/node@npm:16.18.60" + checksum: aa0c81c3f20e663584bf17a5968e54c419277af7982ef41f9d83edd1b7ab4c8af2583a3c8a9e1cf659c6307e6f787e1be20522855121371f5a46d1d54f8a70e3 languageName: node linkType: hard @@ -19215,9 +19228,11 @@ __metadata: linkType: hard "@types/node@npm:^18.17.8": - version: 18.18.5 - resolution: "@types/node@npm:18.18.5" - checksum: fc8c9b2bf226270cf9085a7dac76ce09dd7c3519ec9b687ee2b50385954ab3709c45ca82d002d1536e24286803cd194d7ab7008acebdcd6681b8b19d4277fa5c + version: 18.18.8 + resolution: "@types/node@npm:18.18.8" + dependencies: + undici-types: ~5.26.4 + checksum: d6a82bfc28bca8e4e32ffc9526798d1aea62f6993ea3a535cd3f47ac3f725a48efe3f484d68168dd154af0001c89935e4e1d77e7b1809c3824c6382bf99b86f6 languageName: node linkType: hard @@ -19347,13 +19362,13 @@ __metadata: linkType: hard "@types/pg@npm:^8.6.6": - version: 8.10.7 - resolution: "@types/pg@npm:8.10.7" + version: 8.10.8 + resolution: "@types/pg@npm:8.10.8" dependencies: "@types/node": "*" pg-protocol: "*" pg-types: ^4.0.1 - checksum: 90a616360844b6f877be21a24839af2115f5eb9c8e3eeaf577fa0f036c6c56ad140113fdd8268e63cf215bd0953d89caa1af05191dd89cb2e6d96eb6db6074d2 + checksum: 7f249376c9c959998c01a9886dba45bacaabfbc1783b0083dd22091f67f7ef5fba9db495bef072834380ed29be28e46b39210949f0583527f6f420c8950a9352 languageName: node linkType: hard @@ -19418,11 +19433,11 @@ __metadata: linkType: hard "@types/react-dom@npm:^18": - version: 18.2.13 - resolution: "@types/react-dom@npm:18.2.13" + version: 18.2.14 + resolution: "@types/react-dom@npm:18.2.14" dependencies: "@types/react": "*" - checksum: 22ba066b141dca5a5a9227fae0afc7c94b470fff8e8a38ade72649da57a8ea04d0cb2ba3e22005e7d8e772d49bddd28855b1dd98e6defd033bba6afb6edff883 + checksum: 890289c70d1966c168037637c09cacefe6205bdd27a33252144a6b432595a2943775ac1a1accac0beddaeb67f8fdf721e076acb1adc990b08e51c3d9fd4e780c languageName: node linkType: hard @@ -19520,13 +19535,13 @@ __metadata: linkType: hard "@types/react@npm:^18": - version: 18.2.28 - resolution: "@types/react@npm:18.2.28" + version: 18.2.36 + resolution: "@types/react@npm:18.2.36" dependencies: "@types/prop-types": "*" "@types/scheduler": "*" csstype: ^3.0.2 - checksum: 81381bedeba83278f4c9febb0b83e0bd3f42a25897a50b9cb36ef53651d34b3d50f87ebf11211ea57ea575131f85d31e93e496ce46478a00b0f9bf7b26b5917a + checksum: 561fab294117983f3d245a63730bcffb423fc2a1b0f27d20c870abc5d980bc206a74f741cb11b5170fcdf0e747ac05448369cd930fbf345f74ed567f8fef3a9e languageName: node linkType: hard @@ -19936,9 +19951,9 @@ __metadata: linkType: hard "@types/webpack-env@npm:^1.15.2, @types/webpack-env@npm:^1.15.3": - version: 1.18.2 - resolution: "@types/webpack-env@npm:1.18.2" - checksum: 883908ade827d35a10efc574fb6f2728a7c520d4296cf1507633ac7457204ccd697bc6c8cadac99bc5d96074a6109c658ebfde59f42ba5ba0fdfffc538892b0f + version: 1.18.3 + resolution: "@types/webpack-env@npm:1.18.3" + checksum: f24e82485d8e325b1875608766ba6dad2b2f53a0fb182bc96173b4590110c6b791163402cdf19b50c04e8c05292f227a08aafe9230b2bba52c40c5f7ceccc101 languageName: node linkType: hard @@ -20004,18 +20019,18 @@ __metadata: linkType: hard "@types/yarnpkg__lockfile@npm:^1.1.4": - version: 1.1.7 - resolution: "@types/yarnpkg__lockfile@npm:1.1.7" - checksum: f7d898bfa7a75440ecc57a72d5297c9ce1566d10996004a61765bc79fa82f0c6c82df892442343e983602956f04f0943249902b9e4c09af472873382d0029b21 + version: 1.1.8 + resolution: "@types/yarnpkg__lockfile@npm:1.1.8" + checksum: 96f1c673c0eca3cf55cf48158819625b6a8d203e9762ef0de77d21990def371bf0291fb8374d10fd125fd1571a71bcbed5bc1ca8f188e73032f997a5abee0665 languageName: node linkType: hard "@types/yauzl@npm:^2.10.0": - version: 2.10.1 - resolution: "@types/yauzl@npm:2.10.1" + version: 2.10.2 + resolution: "@types/yauzl@npm:2.10.2" dependencies: "@types/node": "*" - checksum: 3377916a2d493cb2422b167fb7dfff8cb3ea045a9489dab4955858719bf7fe6808e5f6a51ee819904fb7f623f7ac092b87f9d6a857ea1214a45070d19c8b3d7e + checksum: 4ee53b704074064179ed50881b2dfa6f07f8a7032af487f513aa04f0ed333be4ff4231ac8531e6a2024cc45ac69a22e78a2ff4e39a6ed2fe8cc0bfabc353da45 languageName: node linkType: hard @@ -20027,9 +20042,9 @@ __metadata: linkType: hard "@types/zen-observable@npm:^0.8.0, @types/zen-observable@npm:^0.8.2": - version: 0.8.4 - resolution: "@types/zen-observable@npm:0.8.4" - checksum: 784bae5554de07c9b0beda9ff0b81dfa4b52dee2f112d1c874e942114be00133b8159b413c5ba2503b8f0b1baa281c33e91028fe00b44abca0a22552c536e3ec + version: 0.8.5 + resolution: "@types/zen-observable@npm:0.8.5" + checksum: 7a17f4d11cf97ac4abdbdedd18877ad751bcb38f678f58b404e770fd98bf236562f2c20310a1875f835982f3a9c9077b39d972e0be1d54635c5868603605fdf0 languageName: node linkType: hard @@ -20435,17 +20450,17 @@ __metadata: linkType: hard "@vitejs/plugin-react@npm:^4.0.4": - version: 4.1.0 - resolution: "@vitejs/plugin-react@npm:4.1.0" + version: 4.1.1 + resolution: "@vitejs/plugin-react@npm:4.1.1" dependencies: - "@babel/core": ^7.22.20 + "@babel/core": ^7.23.2 "@babel/plugin-transform-react-jsx-self": ^7.22.5 "@babel/plugin-transform-react-jsx-source": ^7.22.5 - "@types/babel__core": ^7.20.2 + "@types/babel__core": ^7.20.3 react-refresh: ^0.14.0 peerDependencies: vite: ^4.2.0 - checksum: 73dd403f5bca4f3f99f0bd3dcbb0cc0ecf88f758b886fb599711be744ca93f20adafe1af3574a998ac7cbd24aaf67ac7fe06983d87088cbdf535540ab402d496 + checksum: 275132ab1e4c227326396aeee93084f20bbe5f0fbe92d45813f3eacd0766eb6e8cd83ee222f90411aefad1ce60fbd31766a8e4725e7bb36914f2bba37afbdebf languageName: node linkType: hard @@ -20782,6 +20797,13 @@ __metadata: languageName: node linkType: hard +"abbrev@npm:^2.0.0": + version: 2.0.0 + resolution: "abbrev@npm:2.0.0" + checksum: 0e994ad2aa6575f94670d8a2149afe94465de9cedaaaac364e7fb43a40c3691c980ff74899f682f4ca58fa96b4cbd7421a015d3a6defe43a442117d7821a2f36 + languageName: node + linkType: hard + "abort-controller@npm:^3.0.0": version: 3.0.0 resolution: "abort-controller@npm:3.0.0" @@ -21449,14 +21471,15 @@ __metadata: languageName: node linkType: hard -"asn1.js@npm:^4.0.0": - version: 4.10.1 - resolution: "asn1.js@npm:4.10.1" +"asn1.js@npm:^5.2.0": + version: 5.4.1 + resolution: "asn1.js@npm:5.4.1" dependencies: bn.js: ^4.0.0 inherits: ^2.0.1 minimalistic-assert: ^1.0.0 - checksum: 9289a1a55401238755e3142511d7b8f6fc32f08c86ff68bd7100da8b6c186179dd6b14234fba2f7f6099afcd6758a816708485efe44bc5b2a6ec87d9ceeddbb5 + safer-buffer: ^2.1.0 + checksum: 3786a101ac6f304bd4e9a7df79549a7561950a13d4bcaec0c7790d44c80d147c1a94ba3d4e663673406064642a40b23fcd6c82a9952468e386c1a1376d747f9a languageName: node linkType: hard @@ -22149,14 +22172,14 @@ __metadata: languageName: node linkType: hard -"better-sqlite3@npm:^8.0.0": - version: 8.7.0 - resolution: "better-sqlite3@npm:8.7.0" +"better-sqlite3@npm:^9.0.0": + version: 9.0.0 + resolution: "better-sqlite3@npm:9.0.0" dependencies: bindings: ^1.5.0 node-gyp: latest prebuild-install: ^7.1.1 - checksum: f1fa38a9a0e4fcd59ececb67c60371b9638d29c19ce9af034421e8a56c9a77e799bb1411b1c3cb08bb9678e15dfb8985553a9ef4098cf5558e7207a3e019f211 + checksum: 53cf439f50768bbcb7adb4894adf6c5134f3479f04084e3009dbe92a00a84e7dd850e4b69262337d807578f3d76e26a40ccebc465e8574e807e27033fab0381a languageName: node linkType: hard @@ -22263,13 +22286,20 @@ __metadata: languageName: node linkType: hard -"bn.js@npm:^4.0.0, bn.js@npm:^4.1.0, bn.js@npm:^4.1.1, bn.js@npm:^4.11.9": +"bn.js@npm:^4.0.0, bn.js@npm:^4.1.0, bn.js@npm:^4.11.9": version: 4.12.0 resolution: "bn.js@npm:4.12.0" checksum: 39afb4f15f4ea537b55eaf1446c896af28ac948fdcf47171961475724d1bb65118cca49fa6e3d67706e4790955ec0e74de584e45c8f1ef89f46c812bee5b5a12 languageName: node linkType: hard +"bn.js@npm:^5.0.0, bn.js@npm:^5.2.1": + version: 5.2.1 + resolution: "bn.js@npm:5.2.1" + checksum: 3dd8c8d38055fedfa95c1d5fc3c99f8dd547b36287b37768db0abab3c239711f88ff58d18d155dd8ad902b0b0cee973747b7ae20ea12a09473272b0201c9edd3 + languageName: node + linkType: hard + "body-parser-xml@npm:^2.0.5": version: 2.0.5 resolution: "body-parser-xml@npm:2.0.5" @@ -22493,28 +22523,30 @@ __metadata: languageName: node linkType: hard -"browserify-rsa@npm:^4.0.0": - version: 4.0.1 - resolution: "browserify-rsa@npm:4.0.1" +"browserify-rsa@npm:^4.0.0, browserify-rsa@npm:^4.1.0": + version: 4.1.0 + resolution: "browserify-rsa@npm:4.1.0" dependencies: - bn.js: ^4.1.0 + bn.js: ^5.0.0 randombytes: ^2.0.1 - checksum: e5d8406e65f8e9a2e038f6fa0cb30108269a1ab33c1563ddc78fb0fff1a43ea21d44bd3dcd01a783683f60dcbc4b58c63120a11f6d09939e3f84af378e6caef8 + checksum: 155f0c135873efc85620571a33d884aa8810e40176125ad424ec9d85016ff105a07f6231650914a760cca66f29af0494087947b7be34880dd4599a0cd3c38e54 languageName: node linkType: hard "browserify-sign@npm:^4.0.0": - version: 4.0.4 - resolution: "browserify-sign@npm:4.0.4" + version: 4.2.2 + resolution: "browserify-sign@npm:4.2.2" dependencies: - bn.js: ^4.1.1 - browserify-rsa: ^4.0.0 - create-hash: ^1.1.0 - create-hmac: ^1.1.2 - elliptic: ^6.0.0 - inherits: ^2.0.1 - parse-asn1: ^5.0.0 - checksum: b1e6f6383f6abbbd5e0f4eb0161cd211cb79af636dd14b5f038db7f3a309b3e026e7e8d7428e3f072a9baace57051a2f45cff311f3b26a901e8be921c3dab847 + bn.js: ^5.2.1 + browserify-rsa: ^4.1.0 + create-hash: ^1.2.0 + create-hmac: ^1.1.7 + elliptic: ^6.5.4 + inherits: ^2.0.4 + parse-asn1: ^5.1.6 + readable-stream: ^3.6.2 + safe-buffer: ^5.2.1 + checksum: b622730c0fc183328c3a1c9fdaaaa5118821ed6822b266fa6b0375db7e20061ebec87301d61931d79b9da9a96ada1cab317fce3c68f233e5e93ed02dbb35544c languageName: node linkType: hard @@ -22736,15 +22768,15 @@ __metadata: languageName: node linkType: hard -"cacache@npm:^17.0.0": - version: 17.1.3 - resolution: "cacache@npm:17.1.3" +"cacache@npm:^18.0.0": + version: 18.0.0 + resolution: "cacache@npm:18.0.0" dependencies: "@npmcli/fs": ^3.1.0 fs-minipass: ^3.0.0 glob: ^10.2.2 - lru-cache: ^7.7.1 - minipass: ^5.0.0 + lru-cache: ^10.0.1 + minipass: ^7.0.3 minipass-collect: ^1.0.2 minipass-flush: ^1.0.5 minipass-pipeline: ^1.2.4 @@ -22752,7 +22784,7 @@ __metadata: ssri: ^10.0.0 tar: ^6.1.11 unique-filename: ^3.0.0 - checksum: 385756781e1e21af089160d89d7462b7ed9883c978e848c7075b90b73cb823680e66092d61513050164588387d2ca87dd6d910e28d64bc13a9ac82cd8580c796 + checksum: 2cd6bf15551abd4165acb3a4d1ef0593b3aa2fd6853ae16b5bb62199c2faecf27d36555a9545c0e07dd03347ec052e782923bdcece724a24611986aafb53e152 languageName: node linkType: hard @@ -23951,8 +23983,8 @@ __metadata: linkType: hard "concurrently@npm:^8.0.0": - version: 8.2.1 - resolution: "concurrently@npm:8.2.1" + version: 8.2.2 + resolution: "concurrently@npm:8.2.2" dependencies: chalk: ^4.1.2 date-fns: ^2.30.0 @@ -23966,7 +23998,7 @@ __metadata: bin: conc: dist/bin/concurrently.js concurrently: dist/bin/concurrently.js - checksum: 216cb16d5b301cbd9c657b19430836d1686fe8fa9b9ef35ef7ac601e1a5cf6535166a3e57de446696dbd5e7e3f45d78fc70f33c5fd4bb565342cd5e752c5b069 + checksum: 8ac774df06869773438f1bf91025180c52d5b53139bc86cf47659136c0d97461d0579c515d848d1e945d4e3e0cafe646b2ea18af8d74259b46abddcfe39b2c6c languageName: node linkType: hard @@ -24016,13 +24048,13 @@ __metadata: languageName: node linkType: hard -"connect-session-knex@npm:^3.0.1": - version: 3.0.1 - resolution: "connect-session-knex@npm:3.0.1" +"connect-session-knex@npm:^4.0.0": + version: 4.0.0 + resolution: "connect-session-knex@npm:4.0.0" dependencies: bluebird: ^3.7.2 - knex: ^2.3.0 - checksum: f5a80c3c34d30e7cd4e79a6aae09d112825986d51ddc3a4563ef95ade425178239d4e3e05420fb3b6204b2353b0dfd754d318b288989b539583f6c0e52758b7a + knex: 3 + checksum: 88454b9b0b78e89cf27fe95a443f8051e43603b68c1c671acfa5a91e1a0abac1e8afd6888e1f3ea53b4b862305e47f6be46c8c4cd238f2f469cba676a25c776e languageName: node linkType: hard @@ -24329,7 +24361,7 @@ __metadata: languageName: node linkType: hard -"create-hash@npm:^1.1.0, create-hash@npm:^1.1.2": +"create-hash@npm:^1.1.0, create-hash@npm:^1.1.2, create-hash@npm:^1.2.0": version: 1.2.0 resolution: "create-hash@npm:1.2.0" dependencies: @@ -24342,7 +24374,7 @@ __metadata: languageName: node linkType: hard -"create-hmac@npm:^1.1.0, create-hmac@npm:^1.1.2, create-hmac@npm:^1.1.4": +"create-hmac@npm:^1.1.0, create-hmac@npm:^1.1.4, create-hmac@npm:^1.1.7": version: 1.1.7 resolution: "create-hmac@npm:1.1.7" dependencies: @@ -26004,7 +26036,7 @@ __metadata: languageName: node linkType: hard -"elliptic@npm:^6.0.0": +"elliptic@npm:^6.0.0, elliptic@npm:^6.5.4": version: 6.5.4 resolution: "elliptic@npm:6.5.4" dependencies: @@ -27511,7 +27543,7 @@ __metadata: "@types/express-serve-static-core": ^4.17.5 "@types/luxon": ^3.0.0 azure-devops-node-api: ^11.0.1 - better-sqlite3: ^8.0.0 + better-sqlite3: ^9.0.0 dockerode: ^3.3.1 example-app: "link:../app" express: ^4.17.1 @@ -27519,7 +27551,7 @@ __metadata: express-promise-router: ^4.1.0 luxon: ^3.0.0 mysql2: ^2.2.5 - pg: ^8.3.0 + pg: ^8.11.3 pg-connection-string: ^2.3.0 prom-client: ^14.0.1 winston: ^3.2.1 @@ -29017,18 +29049,18 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.2.2": - version: 10.2.7 - resolution: "glob@npm:10.2.7" +"glob@npm:^10.2.2, glob@npm:^10.3.10": + version: 10.3.10 + resolution: "glob@npm:10.3.10" dependencies: foreground-child: ^3.1.0 - jackspeak: ^2.0.3 + jackspeak: ^2.3.5 minimatch: ^9.0.1 - minipass: ^5.0.0 || ^6.0.2 - path-scurry: ^1.7.0 + minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 + path-scurry: ^1.10.1 bin: - glob: dist/cjs/src/bin.js - checksum: 555205a74607d6f8d9874ba888924b305b5ea1abfaa2e9ccb11ac713d040aac7edbf7d8702a2f4a1cd81b2d7666412170ce7ef061d33cddde189dae8c1a1a054 + glob: dist/esm/bin.mjs + checksum: 4f2fe2511e157b5a3f525a54092169a5f92405f24d2aed3142f4411df328baca13059f4182f1db1bf933e2c69c0bd89e57ae87edd8950cba8c7ccbe84f721cf3 languageName: node linkType: hard @@ -30114,7 +30146,7 @@ __metadata: languageName: node linkType: hard -"https-proxy-agent@npm:^7.0.2": +"https-proxy-agent@npm:^7.0.1, https-proxy-agent@npm:^7.0.2": version: 7.0.2 resolution: "https-proxy-agent@npm:7.0.2" dependencies: @@ -31393,6 +31425,13 @@ __metadata: languageName: node linkType: hard +"isexe@npm:^3.1.1": + version: 3.1.1 + resolution: "isexe@npm:3.1.1" + checksum: 7fe1931ee4e88eb5aa524cd3ceb8c882537bc3a81b02e438b240e47012eef49c86904d0f0e593ea7c3a9996d18d0f1f3be8d3eaa92333977b0c3a9d353d5563e + languageName: node + linkType: hard + "isobject@npm:^3.0.1": version: 3.0.1 resolution: "isobject@npm:3.0.1" @@ -31595,16 +31634,16 @@ __metadata: languageName: node linkType: hard -"jackspeak@npm:^2.0.3": - version: 2.2.1 - resolution: "jackspeak@npm:2.2.1" +"jackspeak@npm:^2.3.5": + version: 2.3.6 + resolution: "jackspeak@npm:2.3.6" dependencies: "@isaacs/cliui": ^8.0.2 "@pkgjs/parseargs": ^0.11.0 dependenciesMeta: "@pkgjs/parseargs": optional: true - checksum: e29291c0d0f280a063fa18fbd1e891ab8c2d7519fd34052c0ebde38538a15c603140d60c2c7f432375ff7ee4c5f1c10daa8b2ae19a97c3d4affe308c8360c1df + checksum: 57d43ad11eadc98cdfe7496612f6bbb5255ea69fe51ea431162db302c2a11011642f50cfad57288bd0aea78384a0612b16e131944ad8ecd09d619041c8531b54 languageName: node linkType: hard @@ -33199,9 +33238,9 @@ __metadata: languageName: node linkType: hard -"knex@npm:^2.0.0, knex@npm:^2.3.0, knex@npm:^2.4.2": - version: 2.5.1 - resolution: "knex@npm:2.5.1" +"knex@npm:3, knex@npm:^3.0.0": + version: 3.0.1 + resolution: "knex@npm:3.0.1" dependencies: colorette: 2.0.19 commander: ^10.0.0 @@ -33234,7 +33273,7 @@ __metadata: optional: true bin: knex: bin/cli.js - checksum: 4f2da7fda51a450de25274eb76034c869de0427c17831dc8472b8116e879d23aae0592c2ce4e9b2a473417867063ac6e7b29021b39b4a4d502335017a5a09278 + checksum: bcfc3f8da9a7e898a873d2a122856ac9355f5ee1c0ab39534d6cac9ea69388da2fe0fa607b20d65298e191a4377af72f8ff7f4430f8b8c4abc144010b7e9796c languageName: node linkType: hard @@ -34031,6 +34070,13 @@ __metadata: languageName: node linkType: hard +"lru-cache@npm:^10.0.1, lru-cache@npm:^9.1.1 || ^10.0.0": + version: 10.0.1 + resolution: "lru-cache@npm:10.0.1" + checksum: 06f8d0e1ceabd76bb6f644a26dbb0b4c471b79c7b514c13c6856113879b3bf369eb7b497dad4ff2b7e2636db202412394865b33c332100876d838ad1372f0181 + languageName: node + linkType: hard + "lru-cache@npm:^4.0.1, lru-cache@npm:^4.1.3": version: 4.1.5 resolution: "lru-cache@npm:4.1.5" @@ -34066,7 +34112,7 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^9.0.0, lru-cache@npm:^9.1.1": +"lru-cache@npm:^9.0.0": version: 9.1.2 resolution: "lru-cache@npm:9.1.2" checksum: d3415634be3908909081fc4c56371a8d562d9081eba70543d86871b978702fffd0e9e362b83921b27a29ae2b37b90f55675aad770a54ac83bb3e4de5049d4b15 @@ -34179,7 +34225,7 @@ __metadata: languageName: node linkType: hard -"make-fetch-happen@npm:^10.0.1": +"make-fetch-happen@npm:^10.0.1, make-fetch-happen@npm:^10.0.3": version: 10.2.1 resolution: "make-fetch-happen@npm:10.2.1" dependencies: @@ -34203,26 +34249,22 @@ __metadata: languageName: node linkType: hard -"make-fetch-happen@npm:^11.0.3": - version: 11.1.1 - resolution: "make-fetch-happen@npm:11.1.1" +"make-fetch-happen@npm:^13.0.0": + version: 13.0.0 + resolution: "make-fetch-happen@npm:13.0.0" dependencies: - agentkeepalive: ^4.2.1 - cacache: ^17.0.0 + "@npmcli/agent": ^2.0.0 + cacache: ^18.0.0 http-cache-semantics: ^4.1.1 - http-proxy-agent: ^5.0.0 - https-proxy-agent: ^5.0.0 is-lambda: ^1.0.1 - lru-cache: ^7.7.1 - minipass: ^5.0.0 + minipass: ^7.0.2 minipass-fetch: ^3.0.0 minipass-flush: ^1.0.5 minipass-pipeline: ^1.2.4 negotiator: ^0.6.3 promise-retry: ^2.0.1 - socks-proxy-agent: ^7.0.0 ssri: ^10.0.0 - checksum: 7268bf274a0f6dcf0343829489a4506603ff34bd0649c12058753900b0eb29191dce5dba12680719a5d0a983d3e57810f594a12f3c18494e93a1fbc6348a4540 + checksum: 7c7a6d381ce919dd83af398b66459a10e2fe8f4504f340d1d090d3fa3d1b0c93750220e1d898114c64467223504bd258612ba83efbc16f31b075cd56de24b4af languageName: node linkType: hard @@ -35397,10 +35439,10 @@ __metadata: languageName: node linkType: hard -"minipass@npm:^5.0.0 || ^6.0.2": - version: 6.0.2 - resolution: "minipass@npm:6.0.2" - checksum: d140b91f4ab2e5ce5a9b6c468c0e82223504acc89114c1a120d4495188b81fedf8cade72a9f4793642b4e66672f990f1e0d902dd858485216a07cd3c8a62fac9 +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3": + version: 7.0.4 + resolution: "minipass@npm:7.0.4" + checksum: 87585e258b9488caf2e7acea242fd7856bbe9a2c84a7807643513a338d66f368c7d518200ad7b70a508664d408aa000517647b2930c259a8b1f9f0984f344a21 languageName: node linkType: hard @@ -36011,15 +36053,15 @@ __metadata: languageName: node linkType: hard -"node-gyp@npm:^9.4.0, node-gyp@npm:latest": - version: 9.4.0 - resolution: "node-gyp@npm:9.4.0" +"node-gyp@npm:^9.4.0": + version: 9.4.1 + resolution: "node-gyp@npm:9.4.1" dependencies: env-paths: ^2.2.0 exponential-backoff: ^3.1.1 glob: ^7.1.4 graceful-fs: ^4.2.6 - make-fetch-happen: ^11.0.3 + make-fetch-happen: ^10.0.3 nopt: ^6.0.0 npmlog: ^6.0.0 rimraf: ^3.0.2 @@ -36028,7 +36070,27 @@ __metadata: which: ^2.0.2 bin: node-gyp: bin/node-gyp.js - checksum: 78b404e2e0639d64e145845f7f5a3cb20c0520cdaf6dda2f6e025e9b644077202ea7de1232396ba5bde3fee84cdc79604feebe6ba3ec84d464c85d407bb5da99 + checksum: 8576c439e9e925ab50679f87b7dfa7aa6739e42822e2ad4e26c36341c0ba7163fdf5a946f0a67a476d2f24662bc40d6c97bd9e79ced4321506738e6b760a1577 + languageName: node + linkType: hard + +"node-gyp@npm:latest": + version: 10.0.1 + resolution: "node-gyp@npm:10.0.1" + dependencies: + env-paths: ^2.2.0 + exponential-backoff: ^3.1.1 + glob: ^10.3.10 + graceful-fs: ^4.2.6 + make-fetch-happen: ^13.0.0 + nopt: ^7.0.0 + proc-log: ^3.0.0 + semver: ^7.3.5 + tar: ^6.1.2 + which: ^4.0.0 + bin: + node-gyp: bin/node-gyp.js + checksum: 60a74e66d364903ce02049966303a57f898521d139860ac82744a5fdd9f7b7b3b61f75f284f3bfe6e6add3b8f1871ce305a1d41f775c7482de837b50c792223f languageName: node linkType: hard @@ -36200,6 +36262,17 @@ __metadata: languageName: node linkType: hard +"nopt@npm:^7.0.0": + version: 7.2.0 + resolution: "nopt@npm:7.2.0" + dependencies: + abbrev: ^2.0.0 + bin: + nopt: bin/nopt.js + checksum: a9c0f57fb8cb9cc82ae47192ca2b7ef00e199b9480eed202482c962d61b59a7fbe7541920b2a5839a97b42ee39e288c0aed770e38057a608d7f579389dfde410 + languageName: node + linkType: hard + "nopt@npm:~1.0.10": version: 1.0.10 resolution: "nopt@npm:1.0.10" @@ -37134,17 +37207,16 @@ __metadata: languageName: node linkType: hard -"parse-asn1@npm:^5.0.0": - version: 5.1.5 - resolution: "parse-asn1@npm:5.1.5" +"parse-asn1@npm:^5.0.0, parse-asn1@npm:^5.1.6": + version: 5.1.6 + resolution: "parse-asn1@npm:5.1.6" dependencies: - asn1.js: ^4.0.0 + asn1.js: ^5.2.0 browserify-aes: ^1.0.0 - create-hash: ^1.1.0 evp_bytestokey: ^1.0.0 pbkdf2: ^3.0.3 safe-buffer: ^5.1.1 - checksum: e3bf40ce4953ec66754fd692bafdd99d9f00a6bb05822361f47222f959ddf5d1f9928088cda3892433f81eee6394ac1d1d9dd4dbd5d5cdc567b644a2cf860a0a + checksum: 9243311d1f88089bc9f2158972aa38d1abd5452f7b7cabf84954ed766048fe574d434d82c6f5a39b988683e96fb84cd933071dda38927e03469dc8c8d14463c7 languageName: node linkType: hard @@ -37554,13 +37626,13 @@ __metadata: languageName: node linkType: hard -"path-scurry@npm:^1.7.0": - version: 1.9.2 - resolution: "path-scurry@npm:1.9.2" +"path-scurry@npm:^1.10.1": + version: 1.10.1 + resolution: "path-scurry@npm:1.10.1" dependencies: - lru-cache: ^9.1.1 - minipass: ^5.0.0 || ^6.0.2 - checksum: 92888dfb68e285043c6d3291c8e971d5d2bc2f5082f4d7b5392896f34be47024c9d0a8b688dd7ae6d125acc424699195474927cb4f00049a9b1ec7c4256fa8e0 + lru-cache: ^9.1.1 || ^10.0.0 + minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 + checksum: e2557cff3a8fb8bc07afdd6ab163a92587884f9969b05bbbaf6fe7379348bfb09af9ed292af12ed32398b15fb443e81692047b786d1eeb6d898a51eb17ed7d90 languageName: node linkType: hard @@ -37735,7 +37807,7 @@ __metadata: languageName: node linkType: hard -"pg@npm:^8.3.0, pg@npm:^8.9.0": +"pg@npm:^8.11.3, pg@npm:^8.9.0": version: 8.11.3 resolution: "pg@npm:8.11.3" dependencies: @@ -38684,6 +38756,13 @@ __metadata: languageName: node linkType: hard +"proc-log@npm:^3.0.0": + version: 3.0.0 + resolution: "proc-log@npm:3.0.0" + checksum: 02b64e1b3919e63df06f836b98d3af002b5cd92655cab18b5746e37374bfb73e03b84fe305454614b34c25b485cc687a9eebdccf0242cda8fda2475dd2c97e02 + languageName: node + linkType: hard + "process-nextick-args@npm:^2.0.0, process-nextick-args@npm:~2.0.0": version: 2.0.1 resolution: "process-nextick-args@npm:2.0.1" @@ -40066,14 +40145,14 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:3, readable-stream@npm:^3.0.0, readable-stream@npm:^3.0.2, readable-stream@npm:^3.0.6, readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0, readable-stream@npm:^3.5.0, readable-stream@npm:^3.6.0": - version: 3.6.0 - resolution: "readable-stream@npm:3.6.0" +"readable-stream@npm:3, readable-stream@npm:^3.0.0, readable-stream@npm:^3.0.2, readable-stream@npm:^3.0.6, readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0, readable-stream@npm:^3.5.0, readable-stream@npm:^3.6.0, readable-stream@npm:^3.6.2": + version: 3.6.2 + resolution: "readable-stream@npm:3.6.2" dependencies: inherits: ^2.0.3 string_decoder: ^1.1.1 util-deprecate: ^1.0.1 - checksum: d4ea81502d3799439bb955a3a5d1d808592cf3133350ed352aeaa499647858b27b1c4013984900238b0873ec8d0d8defce72469fb7a83e61d53f5ad61cb80dc8 + checksum: bdcbe6c22e846b6af075e32cf8f4751c2576238c5043169a1c221c92ee2878458a816a4ea33f4c67623c0b6827c8a400409bfb3cf0bf3381392d0b1dfb52ac8d languageName: node linkType: hard @@ -41226,7 +41305,7 @@ __metadata: languageName: node linkType: hard -"safe-buffer@npm:5.2.1, safe-buffer@npm:>=5.1.0, safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:^5.1.1, safe-buffer@npm:^5.1.2, safe-buffer@npm:~5.2.0": +"safe-buffer@npm:5.2.1, safe-buffer@npm:>=5.1.0, safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:^5.1.1, safe-buffer@npm:^5.1.2, safe-buffer@npm:^5.2.1, safe-buffer@npm:~5.2.0": version: 5.2.1 resolution: "safe-buffer@npm:5.2.1" checksum: b99c4b41fdd67a6aaf280fcd05e9ffb0813654894223afb78a31f14a19ad220bba8aba1cb14eddce1fcfb037155fe6de4e861784eb434f7d11ed58d1e70dd491 @@ -41978,7 +42057,7 @@ __metadata: languageName: node linkType: hard -"socks-proxy-agent@npm:^8.0.2": +"socks-proxy-agent@npm:^8.0.1, socks-proxy-agent@npm:^8.0.2": version: 8.0.2 resolution: "socks-proxy-agent@npm:8.0.2" dependencies: @@ -44335,10 +44414,10 @@ __metadata: languageName: node linkType: hard -"undici-types@npm:~5.25.1": - version: 5.25.3 - resolution: "undici-types@npm:5.25.3" - checksum: ec9d2cc36520cbd9fbe3b3b6c682a87fe5be214699e1f57d1e3d9a2cb5be422e62735f06e0067dc325fd3dd7404c697e4d479f9147dc8a804e049e29f357f2ff +"undici-types@npm:~5.26.4": + version: 5.26.5 + resolution: "undici-types@npm:5.26.5" + checksum: 3192ef6f3fd5df652f2dc1cd782b49d6ff14dc98e5dced492aa8a8c65425227da5da6aafe22523c67f035a272c599bb89cfe803c1db6311e44bed3042fc25487 languageName: node linkType: hard @@ -45740,6 +45819,17 @@ __metadata: languageName: node linkType: hard +"which@npm:^4.0.0": + version: 4.0.0 + resolution: "which@npm:4.0.0" + dependencies: + isexe: ^3.1.1 + bin: + node-which: bin/which.js + checksum: f17e84c042592c21e23c8195108cff18c64050b9efb8459589116999ea9da6dd1509e6a1bac3aeebefd137be00fabbb61b5c2bc0aa0f8526f32b58ee2f545651 + languageName: node + linkType: hard + "wide-align@npm:^1.1.2": version: 1.1.5 resolution: "wide-align@npm:1.1.5"