Merge branch 'master' of github.com:backstage/backstage into scaffolder-examples

This commit is contained in:
Brian Fletcher
2023-01-05 14:07:35 +00:00
164 changed files with 3271 additions and 1123 deletions
+8
View File
@@ -0,0 +1,8 @@
---
'@backstage/plugin-adr': minor
'@backstage/plugin-adr-backend': patch
---
The ADR plugin can now work with sites other than GitHub. Expanded the ADR backend plugin to provide endpoints to facilitate this.
**BREAKING** The ADR plugin now uses UrlReaders. You will have to [configure integrations](https://backstage.io/docs/integrations/index#configuration) for all sites you want to get ADRs from. If you would like to create your own implementation that has different behavior, you can override the AdrApi [just like you can with other apis.](https://backstage.io/docs/api/utility-apis#app-apis) The previously used Octokit implementation has been completely removed.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-git-release-manager': patch
---
add exports to clear api-report messages
+7
View File
@@ -0,0 +1,7 @@
---
'@backstage/backend-app-api': minor
---
**BREAKING**: The `httpRouterFactory` now accepts a `getPath` option rather than `indexPlugin`. To set up custom index path, configure the new `rootHttpRouterFactory` with a custom `indexPath` instead.
Added an implementation for the new `rootHttpRouterServiceRef`.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder': patch
---
Render the scaffolder action description using the `MarkdownContent` component. This will allow the page to show richer content to describe scaffolder actions.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-common': patch
---
Added `loggerToWinstonLogger`, which was moved from `@backstage/backend-plugin-api`.
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/plugin-scaffolder-backend-module-rails': patch
'@backstage/plugin-scaffolder-backend': patch
---
Change scaffolder task actions to include markdown to demonstrate the new `ActionsPage` markdown feature.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/cli': patch
---
Slightly improve readability of "base URL conflict" error handling code
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-plugin-api': patch
---
Added a new `rootHttpRouterServiceRef` and `RootHttpRouterService` interface.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-test-utils': patch
---
The `startTestBackend` setup now includes default implementations for all core services.
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/plugin-adr-backend': patch
'@backstage/plugin-adr': patch
---
Clarify that default ADR parsers support MADR specification v2.x
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-user-settings': patch
---
Refactor for the feature flag filter functionality
+31
View File
@@ -0,0 +1,31 @@
---
'@backstage/plugin-search-react': minor
---
Allow customizing empty state component through `noResultsComponent` property.
Example:
```jsx
<SearchResult noResultsComponent={<>No results were found</>}>
{({ results }) => (
<List>
{results.map(({ type, document }) => {
switch (type) {
case 'custom-result-item':
return (
<CustomResultListItem key={document.location} result={document} />
);
default:
return (
<DefaultResultListItem
key={document.location}
result={document}
/>
);
}
})}
</List>
)}
</SearchResult>
```
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/backend-plugin-api': patch
'@backstage/backend-common': patch
---
Migrated types related to `TokenManagerService`, `CacheService` and `DatabaseService` into backend-plugin-api.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-lighthouse': patch
---
Fixed bug in Lighthouse Plugin where audit list item and create audit button navigated to a wrong URL.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-plugin-api': minor
---
Moved `loggerToWinstonLogger` to `@backstage/backend-common`.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/cli': patch
---
Removed unused package `type-fest`
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/catalog-client': patch
'@backstage/plugin-catalog-backend': patch
---
Enable the `by-refs` endpoint to receive `fields` through the POST body as well as through query parameters.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-react': patch
---
Add a reusable pop over `EntityPeekAheadPopover` component. It shows more details about the associated entity. See the playbook here https://backstage.io/storybook/?path=/story/catalog-entitypeekaheadpopover--default
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder': patch
---
Updated dependency `use-immer` to `^0.8.0`.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-bitbucket-cloud-common': patch
---
Updated dependency `ts-morph` to `^17.0.0`.
+7
View File
@@ -0,0 +1,7 @@
---
'@backstage/backend-common': patch
'@backstage/backend-test-utils': patch
'@backstage/plugin-catalog-backend': patch
---
Updated dependency `better-sqlite3` to `^8.0.0`.
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/plugin-permission-react': patch
'@backstage/plugin-playlist': patch
---
Updated dependency `swr` to `^2.0.0`.
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/plugin-techdocs-react': patch
'@backstage/plugin-scaffolder': patch
---
Explicitly declaring children as optional props to facilitate react 18 changes
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/repo-tools': patch
---
Updates Api-extractor and api-documenter version
+19
View File
@@ -0,0 +1,19 @@
---
'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch
'@backstage/plugin-catalog-backend-module-bitbucket-server': patch
'@backstage/plugin-catalog-backend-module-bitbucket-cloud': patch
'@backstage/plugin-catalog-backend-module-msgraph': patch
'@backstage/plugin-catalog-backend-module-gerrit': patch
'@backstage/plugin-catalog-backend-module-github': patch
'@backstage/plugin-catalog-backend-module-gitlab': patch
'@backstage/plugin-events-backend-module-aws-sqs': patch
'@backstage/plugin-catalog-backend-module-azure': patch
'@backstage/plugin-catalog-backend-module-aws': patch
'@backstage/plugin-scaffolder-backend': patch
'@backstage/backend-app-api': patch
'@backstage/plugin-catalog-backend': patch
'@backstage/plugin-events-backend': patch
'@backstage/plugin-app-backend': patch
---
Switched imports of `loggerToWinstonLogger` to `@backstage/backend-common`.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-defaults': patch
---
The new root HTTP router service is now installed by default.
@@ -36,6 +36,16 @@ catalog:
- type: url
target: https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/all.yaml
- type: url
target: https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/acme-corp.yaml
rules:
- allow: [User, Group]
- type: url
target: https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/sample-templates/all-templates.yaml
rules:
- allow: [Template]
proxy:
'/circleci/api':
target: https://circleci.com/api/v1.1
-6
View File
@@ -1,6 +0,0 @@
StylesPath = .
Vocab = Backstage
[*.md]
BasedOnStyles = Vale
Vale.Terms = NO
+1 -1
View File
@@ -8,7 +8,7 @@ jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v6
- uses: actions/stale@v7
id: stale
with:
stale-issue-message: >
+1 -1
View File
@@ -52,7 +52,7 @@ jobs:
- name: Docker metadata
id: meta
uses: docker/metadata-action@v3
uses: docker/metadata-action@v4
with:
images: registry.uffizzi.com/${{ env.UUID_TAG_APP }}
tags: type=raw,value=60d
+4 -1
View File
@@ -1,4 +1,7 @@
StylesPath = .github/styles
StylesPath = .github/vale
Vocab = Backstage
[*.md]
BasedOnStyles = Vale
Vale.Terms = NO
+31
View File
@@ -246,6 +246,37 @@ value. These are special in that they form the entity's unique
The return type is JSON, as a single [`Entity`](descriptor-format.md), or a 404
error if there was no entity with that reference triplet.
### `POST /entities/by-refs`
Gets a batch of entities by their entity refs. This is useful in contexts where
you want to fetch a large number of specific entities efficiently, for example
in GraphQL resolvers.
The request body is JSON, on the form
```json
{
"entityRefs": ["component:default/foo", "api:default/bar"],
"fields": ["kind", "metadata.name"]
}
```
where each `entityRefs` entry is an entity ref that you want to fetch. The
`fields` array is optional and works the same way as the `GET /entities` fields
above, e.g. it's used to fetch only certain slices of each entity.
The return type is JSON, on the form
```json
{
"items": [{ "kind": "Component", "metadata": { "name": "foo" } }, null]
}
```
where the `items` array has _the same length_ and _the same order_ as the input
`entityRefs` array. Each element contains the corresponding entity data, or
`null` if no entity existed in the catalog with that ref.
## Locations
TODO
@@ -47,7 +47,7 @@ For this reason, any changes made to the template are documented along with
upgrade instructions in the
[changelog](https://github.com/backstage/backstage/blob/master/packages/create-app/CHANGELOG.md)
of the `@backstage/create-app` package. We recommend peeking at this changelog
-for any applicable updates when upgrading packages. As an alternative, the
for any applicable updates when upgrading packages. As an alternative, the
[Backstage Upgrade Helper](https://backstage.github.io/upgrade-helper/) provides
a consolidated view of all the changes between two versions of Backstage. You
can find the current version of your Backstage installation in `backstage.json`.
+3 -3
View File
@@ -5506,13 +5506,13 @@ __metadata:
linkType: hard
"json5@npm:^1.0.1":
version: 1.0.1
resolution: "json5@npm:1.0.1"
version: 1.0.2
resolution: "json5@npm:1.0.2"
dependencies:
minimist: ^1.2.0
bin:
json5: lib/cli.js
checksum: e76ea23dbb8fc1348c143da628134a98adf4c5a4e8ea2adaa74a80c455fc2cdf0e2e13e6398ef819bfe92306b610ebb2002668ed9fc1af386d593691ef346fc3
checksum: 866458a8c58a95a49bef3adba929c625e82532bcff1fe93f01d29cb02cac7c3fe1f4b79951b7792c2da9de0b32871a8401a6e3c5b36778ad852bf5b8a61165d7
languageName: node
linkType: hard
+1 -1
View File
@@ -11,7 +11,7 @@
"build:backend": "yarn workspace backend build",
"build:all": "backstage-cli repo build --all",
"build:api-reports": "yarn build:api-reports:only --tsc",
"build:api-reports:only": "backstage-repo-tools api-reports --allow-warnings 'packages/core-components,plugins/+(catalog|catalog-import|git-release-manager|jenkins|kubernetes)'",
"build:api-reports:only": "backstage-repo-tools api-reports --allow-warnings 'packages/core-components,plugins/+(catalog|catalog-import|git-release-manager|jenkins|kubernetes)' -o ae-wrong-input-file-type",
"build:api-docs": "LANG=en_EN yarn build:api-reports --docs",
"tsc": "tsc",
"tsc:full": "backstage-cli repo clean && tsc --skipLibCheck false --incremental false",
+18 -5
View File
@@ -4,15 +4,17 @@
```ts
import { BackendFeature } from '@backstage/backend-plugin-api';
import { CacheService } from '@backstage/backend-plugin-api';
import { ConfigService } from '@backstage/backend-plugin-api';
import { DatabaseService } from '@backstage/backend-plugin-api';
import { ExtensionPoint } from '@backstage/backend-plugin-api';
import { Handler } from 'express';
import { HttpRouterService } from '@backstage/backend-plugin-api';
import { LifecycleService } from '@backstage/backend-plugin-api';
import { LoggerService } from '@backstage/backend-plugin-api';
import { PermissionsService } from '@backstage/backend-plugin-api';
import { PluginCacheManager } from '@backstage/backend-common';
import { PluginDatabaseManager } from '@backstage/backend-common';
import { PluginEndpointDiscovery } from '@backstage/backend-common';
import { RootHttpRouterService } from '@backstage/backend-plugin-api';
import { RootLifecycleService } from '@backstage/backend-plugin-api';
import { RootLoggerService } from '@backstage/backend-plugin-api';
import { SchedulerService } from '@backstage/backend-plugin-api';
@@ -34,7 +36,7 @@ export interface Backend {
// @public (undocumented)
export const cacheFactory: (
options?: undefined,
) => ServiceFactory<CacheService>;
) => ServiceFactory<PluginCacheManager>;
// @public (undocumented)
export const configFactory: (
@@ -55,7 +57,7 @@ export interface CreateSpecializedBackendOptions {
// @public (undocumented)
export const databaseFactory: (
options?: undefined,
) => ServiceFactory<DatabaseService>;
) => ServiceFactory<PluginDatabaseManager>;
// @public (undocumented)
export const discoveryFactory: (
@@ -69,7 +71,7 @@ export const httpRouterFactory: (
// @public (undocumented)
export type HttpRouterFactoryOptions = {
indexPlugin?: string;
getPath(pluginId: string): string;
};
// @public
@@ -87,6 +89,17 @@ export const permissionsFactory: (
options?: undefined,
) => ServiceFactory<PermissionsService>;
// @public (undocumented)
export const rootHttpRouterFactory: (
options?: RootHttpRouterFactoryOptions | undefined,
) => ServiceFactory<RootHttpRouterService>;
// @public (undocumented)
export type RootHttpRouterFactoryOptions = {
indexPath?: string | false;
middleware?: Handler[];
};
// @public
export const rootLifecycleFactory: (
options?: undefined,
+1
View File
@@ -38,6 +38,7 @@
"@backstage/backend-tasks": "workspace:^",
"@backstage/errors": "workspace:^",
"@backstage/plugin-permission-node": "workspace:^",
"@types/express": "^4.17.6",
"express": "^4.17.1",
"express-promise-router": "^4.1.0",
"winston": "^3.2.1"
@@ -14,11 +14,13 @@
* limitations under the License.
*/
import { loadBackendConfig } from '@backstage/backend-common';
import {
loadBackendConfig,
loggerToWinstonLogger,
} from '@backstage/backend-common';
import {
coreServices,
createServiceFactory,
loggerToWinstonLogger,
} from '@backstage/backend-plugin-api';
/** @public */
@@ -0,0 +1,70 @@
/*
* Copyright 2022 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
HttpRouterService,
ServiceFactory,
} from '@backstage/backend-plugin-api';
import { httpRouterFactory } from './httpRouterService';
describe('httpRouterFactory', () => {
it('should register plugin paths', async () => {
const rootHttpRouter = { use: jest.fn() };
const factory = httpRouterFactory() as Exclude<
ServiceFactory<HttpRouterService>,
{ scope: 'root' }
>;
const innerFactory = await factory.factory({ rootHttpRouter });
const handler1 = () => {};
const router1 = await innerFactory({ plugin: { getId: () => 'test1' } });
router1.use(handler1);
expect(rootHttpRouter.use).toHaveBeenCalledTimes(1);
expect(rootHttpRouter.use).toHaveBeenCalledWith('/api/test1', handler1);
const handler2 = () => {};
const router2 = await innerFactory({ plugin: { getId: () => 'test2' } });
router2.use(handler2);
expect(rootHttpRouter.use).toHaveBeenCalledTimes(2);
expect(rootHttpRouter.use).toHaveBeenCalledWith('/api/test2', handler2);
});
it('should use custom path generator', async () => {
const rootHttpRouter = { use: jest.fn() };
const factory = httpRouterFactory({
getPath: id => `/some/${id}/path`,
}) as Exclude<ServiceFactory<HttpRouterService>, { scope: 'root' }>;
const innerFactory = await factory.factory({ rootHttpRouter });
const handler1 = () => {};
const router1 = await innerFactory({ plugin: { getId: () => 'test1' } });
router1.use(handler1);
expect(rootHttpRouter.use).toHaveBeenCalledTimes(1);
expect(rootHttpRouter.use).toHaveBeenCalledWith(
'/some/test1/path',
handler1,
);
const handler2 = () => {};
const router2 = await innerFactory({ plugin: { getId: () => 'test2' } });
router2.use(handler2);
expect(rootHttpRouter.use).toHaveBeenCalledTimes(2);
expect(rootHttpRouter.use).toHaveBeenCalledWith(
'/some/test2/path',
handler2,
);
});
});
@@ -18,49 +18,33 @@ import {
createServiceFactory,
coreServices,
} from '@backstage/backend-plugin-api';
import Router from 'express-promise-router';
import { Handler } from 'express';
import { createServiceBuilder } from '@backstage/backend-common';
/**
* @public
*/
export type HttpRouterFactoryOptions = {
/**
* The plugin ID used for the index route. Defaults to 'app'
* A callback used to generate the path for each plugin, defaults to `/api/{pluginId}`.
*/
indexPlugin?: string;
getPath(pluginId: string): string;
};
/** @public */
export const httpRouterFactory = createServiceFactory({
service: coreServices.httpRouter,
deps: {
config: coreServices.config,
plugin: coreServices.pluginMetadata,
rootHttpRouter: coreServices.rootHttpRouter,
},
async factory({ config }, options?: HttpRouterFactoryOptions) {
const defaultPluginId = options?.indexPlugin ?? 'app';
const apiRouter = Router();
const rootRouter = Router();
const service = createServiceBuilder(module)
.loadConfig(config)
.addRouter('/api', apiRouter)
.addRouter('', rootRouter);
await service.start();
async factory({ rootHttpRouter }, options?: HttpRouterFactoryOptions) {
const getPath = options?.getPath ?? (id => `/api/${id}`);
return async ({ plugin }) => {
const pluginId = plugin.getId();
const path = getPath(plugin.getId());
return {
use(handler: Handler) {
if (pluginId === defaultPluginId) {
rootRouter.use(handler);
} else {
apiRouter.use(`/${pluginId}`, handler);
}
rootHttpRouter.use(path, handler);
},
};
};
@@ -25,6 +25,8 @@ export { schedulerFactory } from './schedulerService';
export { tokenManagerFactory } from './tokenManagerService';
export { urlReaderFactory } from './urlReaderService';
export { httpRouterFactory } from './httpRouterService';
export { rootHttpRouterFactory } from './rootHttpRouterService';
export { lifecycleFactory } from './lifecycleService';
export { rootLifecycleFactory } from './rootLifecycleService';
export type { HttpRouterFactoryOptions } from './httpRouterService';
export type { RootHttpRouterFactoryOptions } from './rootHttpRouterService';
@@ -0,0 +1,31 @@
/*
* Copyright 2022 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { findConflictingPath } from './rootHttpRouterService';
describe('findConflictingPath', () => {
it('finds conflicts when present', () => {
expect(findConflictingPath(['/a'], '/a')).toBe('/a');
expect(findConflictingPath(['/b'], '/a')).toBe(undefined);
expect(findConflictingPath(['/a'], '/a/b')).toBe('/a');
expect(findConflictingPath(['/a'], '/aa/b')).toBe(undefined);
expect(findConflictingPath(['/aa'], '/a/b')).toBe(undefined);
expect(findConflictingPath(['/a/b'], '/a')).toBe('/a/b');
expect(findConflictingPath(['/a/b'], '/aa')).toBe(undefined);
expect(findConflictingPath(['/b/a'], '/a')).toBe(undefined);
expect(findConflictingPath(['/a'], '/aa')).toBe(undefined);
});
});
@@ -0,0 +1,125 @@
/*
* Copyright 2022 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
createServiceFactory,
coreServices,
} from '@backstage/backend-plugin-api';
import Router from 'express-promise-router';
import { Handler } from 'express';
import { createServiceBuilder } from '@backstage/backend-common';
/**
* @public
*/
export type RootHttpRouterFactoryOptions = {
/**
* The path to forward all unmatched requests to. Defaults to '/api/app'
*/
indexPath?: string | false;
/**
* Middlewares that are added before all other routes.
*/
middleware?: Handler[];
};
/** @public */
export const rootHttpRouterFactory = createServiceFactory({
service: coreServices.rootHttpRouter,
deps: {
config: coreServices.config,
lifecycle: coreServices.rootLifecycle,
},
async factory({ config, lifecycle }, options?: RootHttpRouterFactoryOptions) {
const indexPath = options?.indexPath ?? '/api/app';
const namedRouter = Router();
const indexRouter = Router();
const service = createServiceBuilder(module).loadConfig(config);
for (const middleware of options?.middleware ?? []) {
service.addRouter('', middleware);
}
service.addRouter('', namedRouter).addRouter('', indexRouter);
const server = await service.start();
// Stop method isn't part of the public API, let's fix that once we move the implementation here.
const stoppableServer = server as typeof server & {
stop: (cb: (error?: Error) => void) => void;
};
lifecycle.addShutdownHook({
async fn() {
await new Promise<void>((resolve, reject) => {
stoppableServer.stop((error?: Error) => {
if (error) {
reject(error);
} else {
resolve();
}
});
});
},
labels: { service: 'rootHttpRouter' },
});
const existingPaths = new Array<string>();
return {
use: (path: string, handler: Handler) => {
if (path.match(/^[/\s]*$/)) {
throw new Error(`Root router path may not be empty`);
}
const conflictingPath = findConflictingPath(existingPaths, path);
if (conflictingPath) {
throw new Error(
`Path ${path} conflicts with the existing path ${conflictingPath}`,
);
}
existingPaths.push(path);
namedRouter.use(path, handler);
if (indexPath === path) {
indexRouter.use(handler);
}
},
};
},
});
function normalizePath(path: string): string {
return path.replace(/\/*$/, '/');
}
export function findConflictingPath(
paths: string[],
newPath: string,
): string | undefined {
const normalizedNewPath = normalizePath(newPath);
for (const path of paths) {
const normalizedPath = normalizePath(path);
if (normalizedPath.startsWith(normalizedNewPath)) {
return path;
}
if (normalizedNewPath.startsWith(normalizedPath)) {
return path;
}
}
return undefined;
}
@@ -13,10 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { loggerToWinstonLogger } from '@backstage/backend-common';
import {
createServiceFactory,
coreServices,
loggerToWinstonLogger,
LifecycleServiceShutdownHook,
RootLifecycleService,
} from '@backstage/backend-plugin-api';
@@ -17,9 +17,11 @@
import {
coreServices,
createServiceFactory,
loggerToWinstonLogger,
} from '@backstage/backend-plugin-api';
import { ServerTokenManager } from '@backstage/backend-common';
import {
loggerToWinstonLogger,
ServerTokenManager,
} from '@backstage/backend-common';
/** @public */
export const tokenManagerFactory = createServiceFactory({
@@ -14,11 +14,10 @@
* limitations under the License.
*/
import { UrlReaders } from '@backstage/backend-common';
import { loggerToWinstonLogger, UrlReaders } from '@backstage/backend-common';
import {
coreServices,
createServiceFactory,
loggerToWinstonLogger,
} from '@backstage/backend-plugin-api';
/** @public */
+20 -37
View File
@@ -12,6 +12,9 @@ import { AzureIntegration } from '@backstage/integration';
import { BitbucketCloudIntegration } from '@backstage/integration';
import { BitbucketIntegration } from '@backstage/integration';
import { BitbucketServerIntegration } from '@backstage/integration';
import { CacheClient } from '@backstage/backend-plugin-api';
import { CacheClientOptions } from '@backstage/backend-plugin-api';
import { CacheClientSetOptions } from '@backstage/backend-plugin-api';
import { Config } from '@backstage/config';
import cors from 'cors';
import Docker from 'dockerode';
@@ -24,12 +27,14 @@ import { GithubCredentialsProvider } from '@backstage/integration';
import { GithubIntegration } from '@backstage/integration';
import { GitLabIntegration } from '@backstage/integration';
import { isChildPath } from '@backstage/cli-common';
import { JsonValue } from '@backstage/types';
import { Knex } from 'knex';
import { KubeConfig } from '@kubernetes/client-node';
import { LoadConfigOptionsRemote } from '@backstage/config-loader';
import { Logger } from 'winston';
import { LoggerService } from '@backstage/backend-plugin-api';
import { MergeResult } from 'isomorphic-git';
import { CacheService as PluginCacheManager } from '@backstage/backend-plugin-api';
import { DatabaseService as PluginDatabaseManager } from '@backstage/backend-plugin-api';
import { DiscoveryService as PluginEndpointDiscovery } from '@backstage/backend-plugin-api';
import { PushResult } from 'isomorphic-git';
import { Readable } from 'stream';
@@ -46,6 +51,8 @@ import { SearchOptions } from '@backstage/backend-plugin-api';
import { SearchResponse } from '@backstage/backend-plugin-api';
import { SearchResponseFile } from '@backstage/backend-plugin-api';
import { Server } from 'http';
import { TokenManagerService as TokenManager } from '@backstage/backend-plugin-api';
import { TransportStreamOptions } from 'winston-transport';
import { UrlReaderService as UrlReader } from '@backstage/backend-plugin-api';
import { V1PodTemplateSpec } from '@kubernetes/client-node';
import * as winston from 'winston';
@@ -163,26 +170,11 @@ export class BitbucketUrlReader implements UrlReader {
toString(): string;
}
// @public
export interface CacheClient {
delete(key: string): Promise<void>;
get(key: string): Promise<JsonValue | undefined>;
set(
key: string,
value: JsonValue,
options?: CacheClientSetOptions,
): Promise<void>;
}
export { CacheClient };
// @public
export type CacheClientOptions = {
defaultTtl?: number;
};
export { CacheClientOptions };
// @public
export type CacheClientSetOptions = {
ttl?: number;
};
export { CacheClientSetOptions };
// @public
export class CacheManager {
@@ -515,21 +507,18 @@ export function loadBackendConfig(options: {
argv: string[];
}): Promise<Config>;
// @public (undocumented)
export function loggerToWinstonLogger(
logger: LoggerService,
opts?: TransportStreamOptions,
): Logger;
// @public
export function notFoundHandler(): RequestHandler;
// @public
export type PluginCacheManager = {
getClient: (options?: CacheClientOptions) => CacheClient;
};
export { PluginCacheManager };
// @public
export interface PluginDatabaseManager {
getClient(): Promise<Knex>;
migrations?: {
skip?: boolean;
};
}
export { PluginDatabaseManager };
export { PluginEndpointDiscovery };
@@ -710,13 +699,7 @@ export interface StatusCheckHandlerOptions {
statusCheck?: StatusCheck;
}
// @public
export interface TokenManager {
authenticate(token: string): Promise<void>;
getToken(): Promise<{
token: string;
}>;
}
export { TokenManager };
export { UrlReader };
+2 -1
View File
@@ -83,6 +83,7 @@
"tar": "^6.1.12",
"uuid": "^8.3.2",
"winston": "^3.2.1",
"winston-transport": "^4.5.0",
"yauzl": "^2.10.0",
"yn": "^4.0.0"
},
@@ -114,7 +115,7 @@
"@types/webpack-env": "^1.15.2",
"@types/yauzl": "^2.10.0",
"aws-sdk-mock": "^5.2.1",
"better-sqlite3": "^7.5.0",
"better-sqlite3": "^8.0.0",
"http-errors": "^2.0.0",
"mock-fs": "^5.1.0",
"msw": "^0.49.0",
+9 -43
View File
@@ -14,57 +14,23 @@
* limitations under the License.
*/
import {
CacheClient,
CacheClientSetOptions,
} from '@backstage/backend-plugin-api';
import { JsonValue } from '@backstage/types';
import { createHash } from 'crypto';
import Keyv from 'keyv';
export type {
CacheClient,
CacheClientSetOptions,
} from '@backstage/backend-plugin-api';
type CacheClientArgs = {
client: Keyv;
};
/**
* Options passed to {@link CacheClient.set}.
*
* @public
*/
export type CacheClientSetOptions = {
/**
* Optional TTL in milliseconds. Defaults to the TTL provided when the client
* was set up (or no TTL if none are provided).
*/
ttl?: number;
};
/**
* A pre-configured, storage agnostic cache client suitable for use by
* Backstage plugins.
*
* @public
*/
export interface CacheClient {
/**
* Reads data from a cache store for the given key. If no data was found,
* returns undefined.
*/
get(key: string): Promise<JsonValue | undefined>;
/**
* Writes the given data to a cache store, associated with the given key. An
* optional TTL may also be provided, otherwise it defaults to the TTL that
* was provided when the client was instantiated.
*/
set(
key: string,
value: JsonValue,
options?: CacheClientSetOptions,
): Promise<void>;
/**
* Removes the given key from the cache store.
*/
delete(key: string): Promise<void>;
}
/**
* A basic, concrete implementation of the CacheClient, suitable for almost
* all uses in Backstage.
+4 -32
View File
@@ -15,21 +15,11 @@
*/
import { Logger } from 'winston';
import { CacheClient } from './CacheClient';
/**
* Options given when constructing a {@link CacheClient}.
*
* @public
*/
export type CacheClientOptions = {
/**
* An optional default TTL (in milliseconds) to be set when getting a client
* instance. If not provided, data will persist indefinitely by default (or
* can be configured per entry at set-time).
*/
defaultTtl?: number;
};
export type {
CacheService as PluginCacheManager,
CacheClientOptions,
} from '@backstage/backend-plugin-api';
/**
* Options given when constructing a {@link CacheManager}.
@@ -48,21 +38,3 @@ export type CacheManagerOptions = {
*/
onError?: (err: Error) => void;
};
/**
* Manages access to cache stores that plugins get.
*
* @public
*/
export type PluginCacheManager = {
/**
* Provides backend plugins cache connections for themselves.
*
* @remarks
*
* The purpose of this method is to allow plugins to get isolated data stores
* so that plugins are discouraged from cache-level integration and/or cache
* key collisions.
*/
getClient: (options?: CacheClientOptions) => CacheClient;
};
+1 -26
View File
@@ -17,32 +17,7 @@
import { Config } from '@backstage/config';
import { Knex } from 'knex';
/**
* The PluginDatabaseManager manages access to databases that Plugins get.
*
* @public
*/
export interface PluginDatabaseManager {
/**
* getClient provides backend plugins database connections for itself.
*
* The purpose of this method is to allow plugins to get isolated data
* stores so that plugins are discouraged from database integration.
*/
getClient(): Promise<Knex>;
/**
* This property is used to control the behavior of database migrations.
*/
migrations?: {
/**
* skip database migrations. Useful if connecting to a read-only database.
*
* @defaultValue false
*/
skip?: boolean;
};
}
export type { DatabaseService as PluginDatabaseManager } from '@backstage/backend-plugin-api';
/**
* DatabaseConnector manages an underlying Knex database driver.
@@ -22,3 +22,4 @@ export {
redactWinstonLogLine,
} from './rootLogger';
export * from './voidLogger';
export { loggerToWinstonLogger } from './loggerToWinstonLogger';
@@ -14,7 +14,7 @@
* limitations under the License.
*/
import { LoggerService } from '../definitions';
import { LoggerService } from '@backstage/backend-plugin-api';
import { Logger as WinstonLogger, createLogger } from 'winston';
import Transport, { TransportStreamOptions } from 'winston-transport';
+1 -23
View File
@@ -14,26 +14,4 @@
* limitations under the License.
*/
/**
* Interface for creating and validating tokens.
*
* @public
*/
export interface TokenManager {
/**
* Fetches a valid token.
*
* @remarks
*
* Tokens are valid for roughly one hour; the actual deadline is set in the
* payload `exp` claim. Never hold on to tokens for reuse; always ask for a
* new one for each outgoing request. This ensures that you always get a
* valid, fresh one.
*/
getToken(): Promise<{ token: string }>;
/**
* Validates a given token.
*/
authenticate(token: string): Promise<void>;
}
export type { TokenManagerService as TokenManager } from '@backstage/backend-plugin-api';
@@ -22,6 +22,7 @@ import {
databaseFactory,
discoveryFactory,
httpRouterFactory,
rootHttpRouterFactory,
lifecycleFactory,
rootLifecycleFactory,
loggerFactory,
@@ -45,6 +46,7 @@ export const defaultServiceFactories = [
tokenManagerFactory,
urlReaderFactory,
httpRouterFactory,
rootHttpRouterFactory,
lifecycleFactory,
rootLifecycleFactory,
];
+47 -17
View File
@@ -7,14 +7,11 @@
import { Config } from '@backstage/config';
import { Handler } from 'express';
import { Logger } from 'winston';
import { JsonValue } from '@backstage/types';
import { Knex } from 'knex';
import { PermissionEvaluator } from '@backstage/plugin-permission-common';
import { PluginCacheManager } from '@backstage/backend-common';
import { PluginDatabaseManager } from '@backstage/backend-common';
import { PluginTaskScheduler } from '@backstage/backend-tasks';
import { Readable } from 'stream';
import { TokenManager } from '@backstage/backend-common';
import { TransportStreamOptions } from 'winston-transport';
// @public (undocumented)
export interface BackendFeature {
@@ -65,8 +62,31 @@ export interface BackendRegistrationPoints {
}): void;
}
// @public (undocumented)
export interface CacheService extends PluginCacheManager {}
// @public
export interface CacheClient {
delete(key: string): Promise<void>;
get(key: string): Promise<JsonValue | undefined>;
set(
key: string,
value: JsonValue,
options?: CacheClientSetOptions,
): Promise<void>;
}
// @public
export type CacheClientOptions = {
defaultTtl?: number;
};
// @public
export type CacheClientSetOptions = {
ttl?: number;
};
// @public
export interface CacheService {
getClient: (options?: CacheClientOptions) => CacheClient;
}
// @public (undocumented)
export interface ConfigService extends Config {}
@@ -82,6 +102,7 @@ export namespace coreServices {
const logger: ServiceRef<LoggerService, 'plugin'>;
const permissions: ServiceRef<PermissionsService, 'plugin'>;
const pluginMetadata: ServiceRef<PluginMetadataService, 'plugin'>;
const rootHttpRouter: ServiceRef<RootHttpRouterService, 'root'>;
const rootLifecycle: ServiceRef<RootLifecycleService, 'root'>;
const rootLogger: ServiceRef<RootLoggerService, 'root'>;
const scheduler: ServiceRef<SchedulerService, 'plugin'>;
@@ -153,8 +174,13 @@ export function createServiceRef<T>(options: {
) => Promise<ServiceFactory<T> | (() => ServiceFactory<T>)>;
}): ServiceRef<T, 'root'>;
// @public (undocumented)
export interface DatabaseService extends PluginDatabaseManager {}
// @public
export interface DatabaseService {
getClient(): Promise<Knex>;
migrations?: {
skip?: boolean;
};
}
// @public
export interface DiscoveryService {
@@ -201,12 +227,6 @@ export interface LoggerService {
warn(message: string, meta?: Error | LogMeta): void;
}
// @public (undocumented)
export function loggerToWinstonLogger(
logger: LoggerService,
opts?: TransportStreamOptions,
): Logger;
// @public (undocumented)
export type LogMeta = {
[name: string]: unknown;
@@ -265,6 +285,11 @@ export type ReadUrlResponse = {
etag?: string;
};
// @public (undocumented)
export interface RootHttpRouterService {
use(path: string, handler: Handler): void;
}
// @public (undocumented)
export interface RootLifecycleService extends LifecycleService {}
@@ -331,8 +356,13 @@ export type ServiceRef<
$$ref: 'service';
};
// @public (undocumented)
export interface TokenManagerService extends TokenManager {}
// @public
export interface TokenManagerService {
authenticate(token: string): Promise<void>;
getToken(): Promise<{
token: string;
}>;
}
// @public (undocumented)
export type TypesToServiceRef<T> = {
+2 -3
View File
@@ -33,14 +33,13 @@
"start": "backstage-cli package start"
},
"dependencies": {
"@backstage/backend-common": "workspace:^",
"@backstage/backend-tasks": "workspace:^",
"@backstage/config": "workspace:^",
"@backstage/plugin-permission-common": "workspace:^",
"@backstage/types": "workspace:^",
"@types/express": "^4.17.6",
"express": "^4.17.1",
"winston": "^3.2.1",
"winston-transport": "^4.5.0"
"knex": "^2.0.0"
},
"devDependencies": {
"@backstage/cli": "workspace:^"
@@ -14,7 +14,79 @@
* limitations under the License.
*/
import { PluginCacheManager } from '@backstage/backend-common';
import { JsonValue } from '@backstage/types';
/** @public */
export interface CacheService extends PluginCacheManager {}
/**
* Manages access to cache stores that plugins get.
*
* @public
*/
export interface CacheService {
/**
* Provides backend plugins cache connections for themselves.
*
* @remarks
*
* The purpose of this method is to allow plugins to get isolated data stores
* so that plugins are discouraged from cache-level integration and/or cache
* key collisions.
*/
getClient: (options?: CacheClientOptions) => CacheClient;
}
/**
* Options passed to {@link CacheClient.set}.
*
* @public
*/
export type CacheClientSetOptions = {
/**
* Optional TTL in milliseconds. Defaults to the TTL provided when the client
* was set up (or no TTL if none are provided).
*/
ttl?: number;
};
/**
* A pre-configured, storage agnostic cache client suitable for use by
* Backstage plugins.
*
* @public
*/
export interface CacheClient {
/**
* Reads data from a cache store for the given key. If no data was found,
* returns undefined.
*/
get(key: string): Promise<JsonValue | undefined>;
/**
* Writes the given data to a cache store, associated with the given key. An
* optional TTL may also be provided, otherwise it defaults to the TTL that
* was provided when the client was instantiated.
*/
set(
key: string,
value: JsonValue,
options?: CacheClientSetOptions,
): Promise<void>;
/**
* Removes the given key from the cache store.
*/
delete(key: string): Promise<void>;
}
/**
* Options given when constructing a {@link CacheClient}.
*
* @public
*/
export type CacheClientOptions = {
/**
* An optional default TTL (in milliseconds) to be set when getting a client
* instance. If not provided, data will persist indefinitely by default (or
* can be configured per entry at set-time).
*/
defaultTtl?: number;
};
@@ -14,7 +14,31 @@
* limitations under the License.
*/
import { PluginDatabaseManager } from '@backstage/backend-common';
import { Knex } from 'knex';
/** @public */
export interface DatabaseService extends PluginDatabaseManager {}
/**
* The DatabaseService manages access to databases that Plugins get.
*gs
* @public
*/
export interface DatabaseService {
/**
* getClient provides backend plugins database connections for itself.
*
* The purpose of this method is to allow plugins to get isolated data
* stores so that plugins are discouraged from database integration.
*/
getClient(): Promise<Knex>;
/**
* This property is used to control the behavior of database migrations.
*/
migrations?: {
/**
* skip database migrations. Useful if connecting to a read-only database.
*
* @defaultValue false
*/
skip?: boolean;
};
}
@@ -0,0 +1,28 @@
/*
* Copyright 2022 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Handler } from 'express';
/**
* @public
*/
export interface RootHttpRouterService {
/**
* Registers a handler at the root of the backend router.
* The path is required and may not be empty.
*/
use(path: string, handler: Handler): void;
}
@@ -14,7 +14,26 @@
* limitations under the License.
*/
import { TokenManager } from '@backstage/backend-common';
/**
* Interface for creating and validating tokens.
*
* @public
*/
export interface TokenManagerService {
/**
* Fetches a valid token.
*
* @remarks
*
* Tokens are valid for roughly one hour; the actual deadline is set in the
* payload `exp` claim. Never hold on to tokens for reuse; always ask for a
* new one for each outgoing request. This ensures that you always get a
* valid, fresh one.
*/
getToken(): Promise<{ token: string }>;
/** @public */
export interface TokenManagerService extends TokenManager {}
/**
* Validates a given token.
*/
authenticate(token: string): Promise<void>;
}
@@ -103,6 +103,15 @@ export namespace coreServices {
import('./PluginMetadataService').PluginMetadataService
>({ id: 'core.pluginMetadata' });
/**
* The service reference for the root scoped {@link RootHttpRouterService}.
*
* @public
*/
export const rootHttpRouter = createServiceRef<
import('./RootHttpRouterService').RootHttpRouterService
>({ id: 'core.rootHttpRouter', scope: 'root' });
/**
* The service reference for the root scoped {@link RootLifecycleService}.
*
@@ -15,7 +15,12 @@
*/
export { coreServices } from './coreServices';
export type { CacheService } from './CacheService';
export type {
CacheService,
CacheClient,
CacheClientOptions,
CacheClientSetOptions,
} from './CacheService';
export type { ConfigService } from './ConfigService';
export type { DatabaseService } from './DatabaseService';
export type { DiscoveryService } from './DiscoveryService';
@@ -27,6 +32,7 @@ export type {
export type { LoggerService, LogMeta } from './LoggerService';
export type { PermissionsService } from './PermissionsService';
export type { PluginMetadataService } from './PluginMetadataService';
export type { RootHttpRouterService } from './RootHttpRouterService';
export type { RootLifecycleService } from './RootLifecycleService';
export type { RootLoggerService } from './RootLoggerService';
export type { SchedulerService } from './SchedulerService';
@@ -15,5 +15,4 @@
*/
export * from './definitions';
export * from './helpers';
export * from './system';
+1 -1
View File
@@ -39,7 +39,7 @@
"@backstage/backend-plugin-api": "workspace:^",
"@backstage/cli": "workspace:^",
"@backstage/config": "workspace:^",
"better-sqlite3": "^7.5.0",
"better-sqlite3": "^8.0.0",
"knex": "^2.0.0",
"msw": "^0.49.0",
"mysql2": "^2.2.5",
+2 -1
View File
@@ -32,6 +32,7 @@
"@backstage/catalog-model": "workspace:^",
"@backstage/config": "workspace:^",
"@backstage/integration": "workspace:^",
"@backstage/plugin-adr-backend": "workspace:^",
"@backstage/plugin-app-backend": "workspace:^",
"@backstage/plugin-auth-backend": "workspace:^",
"@backstage/plugin-auth-node": "workspace:^",
@@ -69,7 +70,7 @@
"@gitbeaker/node": "^35.1.0",
"@octokit/rest": "^19.0.3",
"azure-devops-node-api": "^11.0.1",
"better-sqlite3": "^7.5.0",
"better-sqlite3": "^8.0.0",
"dockerode": "^3.3.1",
"example-app": "link:../app",
"express": "^4.17.1",
+4 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2020 The Backstage Authors
* Copyright 2022 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -61,6 +61,7 @@ import badges from './plugins/badges';
import jenkins from './plugins/jenkins';
import permission from './plugins/permission';
import playlist from './plugins/playlist';
import adr from './plugins/adr';
import { PluginEnvironment } from './types';
import { ServerPermissionClient } from '@backstage/plugin-permission-node';
import { DefaultIdentityClient } from '@backstage/plugin-auth-node';
@@ -139,6 +140,7 @@ async function main() {
const appEnv = useHotMemoize(module, () => createEnv('app'));
const badgesEnv = useHotMemoize(module, () => createEnv('badges'));
const jenkinsEnv = useHotMemoize(module, () => createEnv('jenkins'));
const adrEnv = useHotMemoize(module, () => createEnv('adr'));
const techInsightsEnv = useHotMemoize(module, () =>
createEnv('tech-insights'),
);
@@ -175,6 +177,7 @@ async function main() {
apiRouter.use('/permission', await permission(permissionEnv));
apiRouter.use('/playlist', await playlist(playlistEnv));
apiRouter.use('/explore', await explore(exploreEnv));
apiRouter.use('/adr', await adr(adrEnv));
apiRouter.use(notFoundHandler());
const service = createServiceBuilder(module)
+29
View File
@@ -0,0 +1,29 @@
/*
* Copyright 2022 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { createRouter } from '@backstage/plugin-adr-backend';
import { Router } from 'express';
import { PluginEnvironment } from '../types';
export default async function createPlugin(
env: PluginEnvironment,
): Promise<Router> {
return await createRouter({
reader: env.reader,
cacheClient: env.cache.getClient(),
logger: env.logger,
});
}
@@ -232,9 +232,9 @@ describe('CatalogClient', () => {
};
server.use(
rest.post(`${mockBaseUrl}/entities/by-refs`, async (req, res, ctx) => {
expect(req.url.searchParams.get('fields')).toBe('a,b');
await expect(req.json()).resolves.toEqual({
entityRefs: ['k:n/a', 'k:n/b'],
fields: ['a', 'b'],
});
return res(ctx.json({ items: [entity, null] }));
}),
+4 -5
View File
@@ -197,14 +197,13 @@ export class CatalogClient implements CatalogApi {
request: GetEntitiesByRefsRequest,
options?: CatalogRequestOptions,
): Promise<GetEntitiesByRefsResponse> {
const params: string[] = [];
const body: any = { entityRefs: request.entityRefs };
if (request.fields?.length) {
params.push(`fields=${request.fields.map(encodeURIComponent).join(',')}`);
body.fields = request.fields;
}
const baseUrl = await this.discoveryApi.getBaseUrl('catalog');
const query = params.length ? `?${params.join('&')}` : '';
const url = `${baseUrl}/entities/by-refs${query}`;
const url = `${baseUrl}/entities/by-refs`;
const response = await this.fetchApi.fetch(url, {
headers: {
@@ -212,7 +211,7 @@ export class CatalogClient implements CatalogApi {
...(options?.token && { Authorization: `Bearer ${options?.token}` }),
},
method: 'POST',
body: JSON.stringify({ entityRefs: request.entityRefs }),
body: JSON.stringify(body),
});
if (!response.ok) {
+1 -2
View File
@@ -156,8 +156,7 @@
"mock-fs": "^5.1.0",
"msw": "^0.49.0",
"nodemon": "^2.0.2",
"ts-node": "^10.0.0",
"type-fest": "^2.0.0"
"ts-node": "^10.0.0"
},
"peerDependencies": {
"@microsoft/api-extractor": "^7.21.2"
@@ -80,7 +80,7 @@ export async function startFrontend(options: StartAppOptions) {
`⚠️ Conflict between app baseUrl and backend baseUrl:
app.baseUrl: ${appBaseUrl}
backend.baseUrl: ${appBaseUrl}
backend.baseUrl: ${backendBaseUrl}
Must have unique hostname and/or ports.
+115 -115
View File
@@ -113,7 +113,7 @@ export type BottomLinkProps = {
onClick?: (event: React_2.MouseEvent<HTMLAnchorElement>) => void;
};
// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "Props_19" needs to be exported by the entry point index.d.ts
//
// @public
export function Breadcrumbs(props: Props_19): JSX.Element;
@@ -168,7 +168,7 @@ export interface CodeSnippetProps {
text: string;
}
// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "Props_13" needs to be exported by the entry point index.d.ts
//
// @public
export function Content(props: PropsWithChildren<Props_13>): JSX.Element;
@@ -320,7 +320,7 @@ export function DocsIcon(props: IconComponentProps): JSX.Element;
// @public (undocumented)
export function EmailIcon(props: IconComponentProps): JSX.Element;
// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "Props_2" needs to be exported by the entry point index.d.ts
//
// @public
export function EmptyState(props: Props_2): JSX.Element;
@@ -375,7 +375,7 @@ export type FeatureCalloutCircleClassKey =
| 'pulseCircle'
| 'text';
// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "Props_4" needs to be exported by the entry point index.d.ts
//
// @public
export function FeatureCalloutCircular(
@@ -388,7 +388,7 @@ export type FiltersContainerClassKey = 'root' | 'title';
// @public
export function Gauge(props: GaugeProps): JSX.Element;
// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "Props_10" needs to be exported by the entry point index.d.ts
//
// @public
export function GaugeCard(props: Props_10): JSX.Element;
@@ -432,7 +432,7 @@ export function GitHubIcon(props: IconComponentProps): JSX.Element;
// @public (undocumented)
export function GroupIcon(props: IconComponentProps): JSX.Element;
// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "Props_14" needs to be exported by the entry point index.d.ts
//
// @public
export function Header(props: PropsWithChildren<Props_14>): JSX.Element;
@@ -466,7 +466,7 @@ export type HeaderClassKey =
| 'breadcrumbType'
| 'breadcrumbTitle';
// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "Props_5" needs to be exported by the entry point index.d.ts
//
// @public
export function HeaderIconLinkRow(props: Props_5): JSX.Element;
@@ -497,7 +497,7 @@ export type HeaderTabsClassKey =
// @public (undocumented)
export function HelpIcon(props: IconComponentProps): JSX.Element;
// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "Props_6" needs to be exported by the entry point index.d.ts
//
// @public
export function HorizontalScrollGrid(
@@ -524,7 +524,7 @@ export type IconLinkVerticalClassKey =
| 'secondary'
| 'label';
// Warning: (ae-missing-release-tag) "IconLinkVerticalProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "IconLinkVerticalProps" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type IconLinkVerticalProps = {
@@ -540,7 +540,7 @@ export type IconLinkVerticalProps = {
// @public (undocumented)
export type IdentityProviders = ('guest' | 'custom' | SignInProviderConfig)[];
// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "Props_15" needs to be exported by the entry point index.d.ts
//
// @public
export function InfoCard(props: Props_15): JSX.Element;
@@ -564,7 +564,7 @@ export type InfoCardVariants = 'flex' | 'fullHeight' | 'gridItem';
export function IntroCard(props: IntroCardProps): JSX.Element;
// Warning: (ae-forgotten-export) The symbol "ItemCardProps" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "ItemCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "ItemCard" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public @deprecated
export function ItemCard(props: ItemCardProps): JSX.Element;
@@ -588,7 +588,7 @@ export function ItemCardHeader(props: ItemCardHeaderProps): JSX.Element;
// @public (undocumented)
export type ItemCardHeaderClassKey = 'root';
// Warning: (ae-forgotten-export) The symbol "styles" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "styles_2" needs to be exported by the entry point index.d.ts
//
// @public (undocumented)
export type ItemCardHeaderProps = Partial<WithStyles<typeof styles_2>> & {
@@ -607,29 +607,29 @@ enum LabelPosition {
RIGHT = 'r',
}
// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "Lifecycle" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-forgotten-export) The symbol "Props_7" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "Lifecycle" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function Lifecycle(props: Props_7): JSX.Element;
// Warning: (ae-missing-release-tag) "LifecycleClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "LifecycleClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type LifecycleClassKey = 'alpha' | 'beta';
// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "LinearGauge" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-forgotten-export) The symbol "Props_11" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "LinearGauge" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function LinearGauge(props: Props_11): JSX.Element | null;
// Warning: (ae-missing-release-tag) "Link" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "Link" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
export const Link: (props: LinkProps) => JSX.Element;
// Warning: (ae-missing-release-tag) "LinkProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "LinkProps" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type LinkProps = Omit<LinkProps_2, 'to'> &
@@ -639,7 +639,7 @@ export type LinkProps = Omit<LinkProps_2, 'to'> &
noTrack?: boolean;
};
// Warning: (ae-missing-release-tag) "LoginRequestListItemClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "LoginRequestListItemClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type LoginRequestListItemClassKey = 'root';
@@ -688,49 +688,49 @@ export interface LogViewerProps {
text: string;
}
// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "MarkdownContent" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-forgotten-export) The symbol "Props_8" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "MarkdownContent" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
export function MarkdownContent(props: Props_8): JSX.Element;
// Warning: (ae-missing-release-tag) "MarkdownContentClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "MarkdownContentClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type MarkdownContentClassKey = 'markdown';
// Warning: (ae-missing-release-tag) "MetadataTableCellClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "MetadataTableCellClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type MetadataTableCellClassKey = 'root';
// Warning: (ae-missing-release-tag) "MetadataTableListClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "MetadataTableListClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type MetadataTableListClassKey = 'root';
// Warning: (ae-missing-release-tag) "MetadataTableListItemClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "MetadataTableListItemClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type MetadataTableListItemClassKey = 'root' | 'random';
// Warning: (ae-missing-release-tag) "MetadataTableTitleCellClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "MetadataTableTitleCellClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type MetadataTableTitleCellClassKey = 'root';
// Warning: (ae-missing-release-tag) "MicDropClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "MicDropClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type MicDropClassKey = 'micDrop';
// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "MissingAnnotationEmptyState" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-forgotten-export) The symbol "Props_3" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "MissingAnnotationEmptyState" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function MissingAnnotationEmptyState(props: Props_3): JSX.Element;
// Warning: (ae-missing-release-tag) "MissingAnnotationEmptyStateClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "MissingAnnotationEmptyStateClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type MissingAnnotationEmptyStateClassKey = 'code';
@@ -743,12 +743,12 @@ export type MobileSidebarProps = {
children?: React_2.ReactNode;
};
// Warning: (ae-missing-release-tag) "OAuthRequestDialog" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "OAuthRequestDialog" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function OAuthRequestDialog(_props: {}): JSX.Element;
// Warning: (ae-missing-release-tag) "OAuthRequestDialogClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "OAuthRequestDialogClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type OAuthRequestDialogClassKey =
@@ -757,42 +757,42 @@ export type OAuthRequestDialogClassKey =
| 'contentList'
| 'actionButtons';
// Warning: (ae-missing-release-tag) "OpenedDropdownClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "OpenedDropdownClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type OpenedDropdownClassKey = 'icon';
// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "OverflowTooltip" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-forgotten-export) The symbol "Props_9" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "OverflowTooltip" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function OverflowTooltip(props: Props_9): JSX.Element;
// Warning: (ae-missing-release-tag) "OverflowTooltipClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "OverflowTooltipClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type OverflowTooltipClassKey = 'container';
// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "Page" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-forgotten-export) The symbol "Props_16" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "Page" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function Page(props: Props_16): JSX.Element;
// Warning: (ae-missing-release-tag) "PageClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "PageClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type PageClassKey = 'root';
// Warning: (ae-forgotten-export) The symbol "PageWithHeaderProps" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "PageWithHeader" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "PageWithHeader" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function PageWithHeader(
props: PropsWithChildren<PageWithHeaderProps>,
): JSX.Element;
// Warning: (ae-missing-release-tag) "Progress" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "Progress" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function Progress(
@@ -810,7 +810,7 @@ export type ProxiedSignInPageProps = SignInPageProps & {
headers?: HeadersInit | (() => HeadersInit) | (() => Promise<HeadersInit>);
};
// Warning: (ae-missing-release-tag) "Ranker" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "Ranker" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
enum Ranker {
@@ -819,14 +819,14 @@ enum Ranker {
TIGHT_TREE = 'tight-tree',
}
// Warning: (ae-missing-release-tag) "RenderLabelFunction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "RenderLabelFunction" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
type RenderLabelFunction<T = {}> = (
props: RenderLabelProps<T>,
) => React_2.ReactNode;
// Warning: (ae-missing-release-tag) "RenderLabelProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "RenderLabelProps" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-unresolved-link) The @link reference could not be resolved: This type of declaration is not supported yet by the resolver
// Warning: (ae-unresolved-link) The @link reference could not be resolved: This type of declaration is not supported yet by the resolver
//
@@ -835,7 +835,7 @@ type RenderLabelProps<T = unknown> = {
edge: DependencyEdge<T>;
};
// Warning: (ae-missing-release-tag) "RenderNodeFunction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "RenderNodeFunction" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-unresolved-link) The @link reference could not be resolved: This type of declaration is not supported yet by the resolver
//
// @public
@@ -843,7 +843,7 @@ type RenderNodeFunction<T = {}> = (
props: RenderNodeProps<T>,
) => React_2.ReactNode;
// Warning: (ae-missing-release-tag) "RenderNodeProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "RenderNodeProps" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-unresolved-link) The @link reference could not be resolved: This type of declaration is not supported yet by the resolver
// Warning: (ae-unresolved-link) The @link reference could not be resolved: This type of declaration is not supported yet by the resolver
//
@@ -852,17 +852,17 @@ type RenderNodeProps<T = unknown> = {
node: DependencyNode<T>;
};
// Warning: (ae-missing-release-tag) "ResponseErrorPanel" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "ResponseErrorPanel" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
export function ResponseErrorPanel(props: ErrorPanelProps): JSX.Element;
// Warning: (ae-missing-release-tag) "ResponseErrorPanelClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "ResponseErrorPanelClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type ResponseErrorPanelClassKey = 'text' | 'divider';
// Warning: (ae-missing-release-tag) "RoutedTabs" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "RoutedTabs" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function RoutedTabs(props: { routes: SubRoute_2[] }): JSX.Element;
@@ -896,7 +896,7 @@ export type SelectItem = {
// @public
export const Sidebar: (props: SidebarProps) => JSX.Element;
// Warning: (ae-missing-release-tag) "SIDEBAR_INTRO_LOCAL_STORAGE" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "SIDEBAR_INTRO_LOCAL_STORAGE" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const SIDEBAR_INTRO_LOCAL_STORAGE =
@@ -905,7 +905,7 @@ export const SIDEBAR_INTRO_LOCAL_STORAGE =
// @public (undocumented)
export type SidebarClassKey = 'drawer' | 'drawerOpen';
// Warning: (ae-missing-release-tag) "sidebarConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "sidebarConfig" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const sidebarConfig: {
@@ -933,7 +933,7 @@ export type SidebarContextType = {
setOpen: (open: boolean) => void;
};
// Warning: (ae-missing-release-tag) "SidebarDivider" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "SidebarDivider" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const SidebarDivider: React_2.ComponentType<
@@ -942,7 +942,7 @@ export const SidebarDivider: React_2.ComponentType<
StyledComponentProps<'root'>
>;
// Warning: (ae-missing-release-tag) "SidebarDividerClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "SidebarDividerClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type SidebarDividerClassKey = 'root';
@@ -960,7 +960,7 @@ export interface SidebarGroupProps extends BottomNavigationActionProps {
to?: string;
}
// Warning: (ae-missing-release-tag) "SidebarIntro" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "SidebarIntro" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function SidebarIntro(_props: {}): JSX.Element | null;
@@ -974,7 +974,7 @@ export type SidebarIntroClassKey =
| 'introDismissIcon';
// Warning: (ae-forgotten-export) The symbol "SidebarItemProps" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "SidebarItem" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "SidebarItem" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
export const SidebarItem: (props: SidebarItemProps) => JSX.Element;
@@ -1018,12 +1018,12 @@ export type SidebarOptions = {
drawerWidthOpen?: number;
};
// Warning: (ae-missing-release-tag) "SidebarPage" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "SidebarPage" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function SidebarPage(props: SidebarPageProps): JSX.Element;
// Warning: (ae-missing-release-tag) "SidebarPageClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "SidebarPageClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type SidebarPageClassKey = 'root';
@@ -1066,7 +1066,7 @@ export type SidebarProps = {
children?: React_2.ReactNode;
};
// Warning: (ae-missing-release-tag) "SidebarScrollWrapper" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "SidebarScrollWrapper" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const SidebarScrollWrapper: React_2.ComponentType<
@@ -1076,12 +1076,12 @@ export const SidebarScrollWrapper: React_2.ComponentType<
>;
// Warning: (ae-forgotten-export) The symbol "SidebarSearchFieldProps" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "SidebarSearchField" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "SidebarSearchField" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function SidebarSearchField(props: SidebarSearchFieldProps): JSX.Element;
// Warning: (ae-missing-release-tag) "SidebarSpace" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "SidebarSpace" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const SidebarSpace: React_2.ComponentType<
@@ -1090,12 +1090,12 @@ export const SidebarSpace: React_2.ComponentType<
StyledComponentProps<'root'>
>;
// Warning: (ae-missing-release-tag) "SidebarSpaceClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "SidebarSpaceClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type SidebarSpaceClassKey = 'root';
// Warning: (ae-missing-release-tag) "SidebarSpacer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "SidebarSpacer" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const SidebarSpacer: React_2.ComponentType<
@@ -1104,7 +1104,7 @@ export const SidebarSpacer: React_2.ComponentType<
StyledComponentProps<'root'>
>;
// Warning: (ae-missing-release-tag) "SidebarSpacerClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "SidebarSpacerClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type SidebarSpacerClassKey = 'root';
@@ -1138,18 +1138,18 @@ export type SidebarSubmenuProps = {
children: ReactNode;
};
// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "SignInPage" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-forgotten-export) The symbol "Props_17" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "SignInPage" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function SignInPage(props: Props_17): JSX.Element;
// Warning: (ae-missing-release-tag) "SignInPageClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "SignInPageClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type SignInPageClassKey = 'container' | 'item';
// Warning: (ae-missing-release-tag) "SignInProviderConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "SignInProviderConfig" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type SignInProviderConfig = {
@@ -1160,37 +1160,37 @@ export type SignInProviderConfig = {
};
// Warning: (ae-forgotten-export) The symbol "StepperProps" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "SimpleStepper" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "SimpleStepper" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function SimpleStepper(
props: PropsWithChildren<StepperProps>,
): JSX.Element;
// Warning: (ae-missing-release-tag) "SimpleStepperFooterClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "SimpleStepperFooterClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type SimpleStepperFooterClassKey = 'root';
// Warning: (ae-forgotten-export) The symbol "StepProps" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "SimpleStepperStep" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "SimpleStepperStep" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function SimpleStepperStep(
props: PropsWithChildren<StepProps>,
): JSX.Element;
// Warning: (ae-missing-release-tag) "SimpleStepperStepClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "SimpleStepperStepClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type SimpleStepperStepClassKey = 'end';
// Warning: (ae-missing-release-tag) "StatusAborted" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "StatusAborted" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function StatusAborted(props: PropsWithChildren<{}>): JSX.Element;
// Warning: (ae-missing-release-tag) "StatusClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "StatusClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type StatusClassKey =
@@ -1202,43 +1202,43 @@ export type StatusClassKey =
| 'running'
| 'aborted';
// Warning: (ae-missing-release-tag) "StatusError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "StatusError" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function StatusError(props: PropsWithChildren<{}>): JSX.Element;
// Warning: (ae-missing-release-tag) "StatusOK" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "StatusOK" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function StatusOK(props: PropsWithChildren<{}>): JSX.Element;
// Warning: (ae-missing-release-tag) "StatusPending" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "StatusPending" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function StatusPending(props: PropsWithChildren<{}>): JSX.Element;
// Warning: (ae-missing-release-tag) "StatusRunning" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "StatusRunning" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function StatusRunning(props: PropsWithChildren<{}>): JSX.Element;
// Warning: (ae-missing-release-tag) "StatusWarning" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "StatusWarning" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function StatusWarning(props: PropsWithChildren<{}>): JSX.Element;
// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "StructuredMetadataTable" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-forgotten-export) The symbol "Props_12" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "StructuredMetadataTable" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function StructuredMetadataTable(props: Props_12): JSX.Element;
// Warning: (ae-missing-release-tag) "StructuredMetadataTableListClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "StructuredMetadataTableListClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type StructuredMetadataTableListClassKey = 'root';
// Warning: (ae-missing-release-tag) "StructuredMetadataTableNestedListClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "StructuredMetadataTableNestedListClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type StructuredMetadataTableNestedListClassKey = 'root';
@@ -1250,28 +1250,28 @@ export type SubmenuOptions = {
};
// Warning: (ae-forgotten-export) The symbol "SubvalueCellProps" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "SubvalueCell" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "SubvalueCell" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function SubvalueCell(props: SubvalueCellProps): JSX.Element;
// Warning: (ae-missing-release-tag) "SubvalueCellClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "SubvalueCellClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type SubvalueCellClassKey = 'value' | 'subvalue';
// Warning: (ae-forgotten-export) The symbol "SupportButtonProps" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "SupportButton" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "SupportButton" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function SupportButton(props: SupportButtonProps): JSX.Element;
// Warning: (ae-missing-release-tag) "SupportButtonClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "SupportButtonClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type SupportButtonClassKey = 'popoverList';
// Warning: (ae-missing-release-tag) "SupportConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "SupportConfig" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type SupportConfig = {
@@ -1279,7 +1279,7 @@ export type SupportConfig = {
items: SupportItem[];
};
// Warning: (ae-missing-release-tag) "SupportItem" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "SupportItem" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type SupportItem = {
@@ -1288,7 +1288,7 @@ export type SupportItem = {
links: SupportItemLink[];
};
// Warning: (ae-missing-release-tag) "SupportItemLink" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "SupportItemLink" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type SupportItemLink = {
@@ -1296,7 +1296,7 @@ export type SupportItemLink = {
title: string;
};
// Warning: (ae-missing-release-tag) "Tab" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "Tab" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type Tab = {
@@ -1310,24 +1310,24 @@ export type Tab = {
>;
};
// Warning: (ae-missing-release-tag) "TabBarClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "TabBarClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type TabBarClassKey = 'indicator' | 'flexContainer' | 'root';
// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "TabbedCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-forgotten-export) The symbol "Props_18" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "TabbedCard" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function TabbedCard(props: PropsWithChildren<Props_18>): JSX.Element;
// Warning: (ae-missing-release-tag) "TabbedCardClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "TabbedCardClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type TabbedCardClassKey = 'root' | 'indicator';
// Warning: (ae-missing-release-tag) "TabbedLayout" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "TabbedLayout" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "TabbedLayout" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "TabbedLayout" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
export function TabbedLayout(props: PropsWithChildren<{}>): JSX.Element;
@@ -1343,12 +1343,12 @@ export namespace TabbedLayout {
// @public (undocumented)
export type TabClassKey = 'root' | 'selected';
// Warning: (ae-missing-release-tag) "TabIconClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "TabIconClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type TabIconClassKey = 'root';
// Warning: (ae-missing-release-tag) "Table" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "Table" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function Table<T extends object = {}>(props: TableProps<T>): JSX.Element;
@@ -1359,12 +1359,12 @@ export namespace Table {
icons: Readonly<Icons>;
}
// Warning: (ae-missing-release-tag) "TableClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "TableClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type TableClassKey = 'root';
// Warning: (ae-missing-release-tag) "TableColumn" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "TableColumn" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export interface TableColumn<T extends object = {}> extends Column<T> {
@@ -1374,7 +1374,7 @@ export interface TableColumn<T extends object = {}> extends Column<T> {
width?: string;
}
// Warning: (ae-missing-release-tag) "TableFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "TableFilter" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type TableFilter = {
@@ -1382,17 +1382,17 @@ export type TableFilter = {
type: 'select' | 'multiple-select';
};
// Warning: (ae-missing-release-tag) "TableFiltersClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "TableFiltersClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type TableFiltersClassKey = 'root' | 'value' | 'heder' | 'filters';
// Warning: (ae-missing-release-tag) "TableHeaderClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "TableHeaderClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type TableHeaderClassKey = 'header';
// Warning: (ae-missing-release-tag) "TableProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "TableProps" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export interface TableProps<T extends object = {}>
@@ -1411,7 +1411,7 @@ export interface TableProps<T extends object = {}>
subtitle?: string;
}
// Warning: (ae-missing-release-tag) "TableState" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "TableState" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type TableState = {
@@ -1420,23 +1420,23 @@ export type TableState = {
filters?: SelectedFilters;
};
// Warning: (ae-missing-release-tag) "TableToolbarClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "TableToolbarClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type TableToolbarClassKey = 'root' | 'title' | 'searchField';
// Warning: (ae-forgotten-export) The symbol "TabsProps" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "Tabs" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "Tabs" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function Tabs(props: TabsProps): JSX.Element;
// Warning: (ae-missing-release-tag) "TabsClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "TabsClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type TabsClassKey = 'root' | 'styledTabs' | 'appbar';
// Warning: (ae-missing-release-tag) "TrendLine" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "TrendLine" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function TrendLine(
@@ -1453,7 +1453,7 @@ export function useContent(): {
};
// Warning: (ae-forgotten-export) The symbol "SetQueryParams" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "useQueryParamState" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "useQueryParamState" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function useQueryParamState<T>(
@@ -1502,7 +1502,7 @@ export const useSidebarOpenState: () => SidebarOpenState;
// @public
export const useSidebarPinState: () => SidebarPinState;
// Warning: (ae-missing-release-tag) "useSupportConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "useSupportConfig" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function useSupportConfig(): SupportConfig;
@@ -1511,12 +1511,12 @@ export function useSupportConfig(): SupportConfig;
export function WarningIcon(props: IconComponentProps): JSX.Element;
// Warning: (ae-forgotten-export) The symbol "WarningProps" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "WarningPanel" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "WarningPanel" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
export function WarningPanel(props: WarningProps): JSX.Element;
// Warning: (ae-missing-release-tag) "WarningPanelClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "WarningPanelClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type WarningPanelClassKey =
@@ -1530,7 +1530,7 @@ export type WarningPanelClassKey =
//
// src/components/DependencyGraph/types.d.ts:16:5 - (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/core-components" does not have an export "DependencyNode"
// src/components/DependencyGraph/types.d.ts:20:5 - (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/core-components" does not have an export "DependencyNode"
// src/components/TabbedLayout/RoutedTabs.d.ts:9:5 - (ae-forgotten-export) The symbol "SubRoute" needs to be exported by the entry point index.d.ts
// src/components/TabbedLayout/RoutedTabs.d.ts:9:5 - (ae-forgotten-export) The symbol "SubRoute_2" needs to be exported by the entry point index.d.ts
// src/components/Table/Table.d.ts:20:5 - (ae-forgotten-export) The symbol "SelectedFilters" needs to be exported by the entry point index.d.ts
// src/layout/ErrorBoundary/ErrorBoundary.d.ts:8:5 - (ae-forgotten-export) The symbol "SlackChannel" needs to be exported by the entry point index.d.ts
```
+1 -1
View File
@@ -40,7 +40,7 @@
"handlebars": "^4.7.3",
"nodemon": "^2.0.2",
"pgtools": "^0.3.0",
"puppeteer": "^17.0.0",
"puppeteer": "^19.0.0",
"tree-kill": "^1.2.2",
"ts-node": "^10.0.0"
},
+1 -1
View File
@@ -22,7 +22,7 @@ import {
ChildProcess,
} from 'child_process';
import { promisify } from 'util';
import puppeteer from 'puppeteer';
import * as puppeteer from 'puppeteer';
const execFile = promisify(execFileCb);
+2 -3
View File
@@ -33,8 +33,8 @@
"@backstage/cli-common": "workspace:^",
"@backstage/errors": "workspace:^",
"@manypkg/get-packages": "^1.1.3",
"@microsoft/api-documenter": "^7.17.11",
"@microsoft/api-extractor": "^7.23.0",
"@microsoft/api-documenter": "^7.19.27",
"@microsoft/api-extractor": "^7.33.7",
"chalk": "^4.0.0",
"commander": "^9.1.0",
"fs-extra": "10.1.0",
@@ -53,7 +53,6 @@
"@microsoft/api-extractor-model": "*",
"@microsoft/tsdoc": "*",
"@microsoft/tsdoc-config": "*",
"@rushstack/node-core-library": "*",
"prettier": "^2.8.1",
"typescript": "> 3.0.0"
},
@@ -18,11 +18,9 @@ import {
resolve as resolvePath,
relative as relativePath,
basename,
dirname,
join,
} from 'path';
import { execFile } from 'child_process';
import type prettierType from 'prettier';
import fs from 'fs-extra';
import {
Extractor,
@@ -70,32 +68,7 @@ const tmpDir = cliPaths.resolveTargetRoot(
);
/**
* All of this monkey patching below is because MUI has these bare package.json file as a method
* for making TypeScript accept imports like `@material-ui/core/Button`, and improve tree-shaking
* by declaring them side effect free.
*
* The package.json lookup logic in api-extractor really doesn't like that though, as it enforces
* that the 'name' field exists in all package.json files that it discovers. This below is just
* making sure that we ignore those file package.json files instead of crashing.
*/
const {
PackageJsonLookup,
} = require('@rushstack/node-core-library/lib/PackageJsonLookup');
const old = PackageJsonLookup.prototype.tryGetPackageJsonFilePathFor;
PackageJsonLookup.prototype.tryGetPackageJsonFilePathFor =
function tryGetPackageJsonFilePathForPatch(path: string) {
if (
path.includes('@material-ui') &&
!dirname(path).endsWith('@material-ui')
) {
return undefined;
}
return old.call(this, path);
};
/**
* Another monkey patch where we apply prettier to the API reports. This has to be patched into
* All of this monkey patching below is for apply prettier to the API reports. This has to be patched into
* the middle of the process as API Extractor does a comparison of the contents of the old
* and new files during generation. This inserts the formatting just before that comparison.
*/
@@ -134,7 +107,6 @@ ApiReportGenerator.generateReviewFileContent =
...moreArgs: any[]
) {
const program = collector.program as Program;
// The purpose of this override is to allow the @ignore tag to be used to ignore warnings
// of the form "Warning: (ae-forgotten-export) The symbol "FooBar" needs to be exported by the entry point index.d.ts"
patchFileMessageFetcher(
@@ -166,7 +138,16 @@ ApiReportGenerator.generateReviewFileContent =
}
// The local name of the symbol within the file, rather than the exported name
const localName = (sourceFile as any).identifiers?.get(symbolName);
let localName = (sourceFile as any).identifiers?.get(symbolName);
if (!localName) {
// Sometimes the symbol name is suffixed with a number to disambiguate,
// e.g. "Props_14" instead of "Props" if there are multiple Props interfaces
// so we tyry to strip that suffix and look up the symbol again.
const [, trimmedSymbolName] = symbolName.match(/(.*)_\d+/) || [];
localName = (sourceFile as any).identifiers?.get(trimmedSymbolName);
}
if (!localName) {
throw new Error(
`Unable to find local name of "${symbolName}" in ${sourceFile.fileName}`,
@@ -213,7 +194,7 @@ ApiReportGenerator.generateReviewFileContent =
);
try {
const prettier = require('prettier') as typeof prettierType;
const prettier = require('prettier') as typeof import('prettier');
const config = prettier.resolveConfig.sync(cliPaths.targetRoot) ?? {};
return prettier.format(content, {
@@ -221,7 +202,6 @@ ApiReportGenerator.generateReviewFileContent =
parser: 'markdown',
});
} catch (e) {
// console.warn('Failed to format API report with prettier', e);
return content;
}
};
@@ -434,6 +414,7 @@ export async function runApiExtraction({
configObjectFullPath: projectFolder,
packageJsonFullPath: resolvePath(projectFolder, 'package.json'),
tsdocConfigFile: await getTsDocConfig(),
ignoreMissingEntryPoint: true,
});
// The `packageFolder` needs to point to the location within `dist-types` in order for relative
+3 -1
View File
@@ -4,6 +4,8 @@ This ADR backend plugin is primarily responsible for the following:
- Provides a `DefaultAdrCollatorFactory`, which can be used in the search backend to index ADR documents associated with entities to your Backstage Search.
- Provides endpoints that use UrlReaders for getting ADR documents (used in the [ADR frontend plugin](../adr/README.md)).
## Indexing ADR documents for search
Before you are able to start indexing ADR documents to search, you need to go through the [search getting started guide](https://backstage.io/docs/features/search/getting-started).
@@ -35,7 +37,7 @@ indexBuilder.addCollator({
### Parsing custom ADR document formats
By default, the `DefaultAdrCollatorFactory` will parse and index documents that follow the [MADR](https://adr.github.io/madr/) standard file name and template format. If you use a different ADR format and file name convention, you can configure `DefaultAdrCollatorFactory` with custom `adrFilePathFilterFn` and `parser` options (see type definitions for details):
By default, the `DefaultAdrCollatorFactory` will parse and index documents that follow the [MADR v2.x standard file name and template format](https://github.com/adr/madr/tree/2.1.2). If you use a different ADR format and file name convention, you can configure `DefaultAdrCollatorFactory` with custom `adrFilePathFilterFn` and `parser` options (see type definitions for details):
```ts
DefaultAdrCollatorFactory.fromConfig({
+14
View File
@@ -7,10 +7,12 @@
import { AdrDocument } from '@backstage/plugin-adr-common';
import { AdrFilePathFilterFn } from '@backstage/plugin-adr-common';
import { CacheClient } from '@backstage/backend-common';
import { CatalogApi } from '@backstage/catalog-client';
import { Config } from '@backstage/config';
import { DocumentCollatorFactory } from '@backstage/plugin-search-common';
import { Entity } from '@backstage/catalog-model';
import express from 'express';
import { Logger } from 'winston';
import { PluginCacheManager } from '@backstage/backend-common';
import { PluginEndpointDiscovery } from '@backstage/backend-common';
@@ -41,9 +43,21 @@ export type AdrParserContext = {
path: string;
};
// @public (undocumented)
export type AdrRouterOptions = {
reader: UrlReader;
cacheClient: CacheClient;
logger: Logger;
};
// @public
export const createMadrParser: (options?: MadrParserOptions) => AdrParser;
// @public (undocumented)
export function createRouter(
options: AdrRouterOptions,
): Promise<express.Router>;
// @public
export class DefaultAdrCollatorFactory implements DocumentCollatorFactory {
// (undocumented)
+3
View File
@@ -36,6 +36,9 @@
"@backstage/integration": "workspace:^",
"@backstage/plugin-adr-common": "workspace:^",
"@backstage/plugin-search-common": "workspace:^",
"@types/express": "^4.17.15",
"express": "^4.18.2",
"express-promise-router": "^4.1.1",
"luxon": "^3.0.0",
"marked": "^4.0.14",
"node-fetch": "^2.6.5",
+1
View File
@@ -21,3 +21,4 @@
*/
export * from './search';
export * from './service';
@@ -14,4 +14,5 @@
* limitations under the License.
*/
export { loggerToWinstonLogger } from './loggerToWinstonLogger';
export { createRouter } from './router';
export type { AdrRouterOptions } from './router';
@@ -0,0 +1,229 @@
/*
* Copyright 2022 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
CacheClient,
ReadTreeResponse,
ReadTreeResponseFile,
ReadUrlResponse,
UrlReader,
} from '@backstage/backend-common';
import express from 'express';
import request from 'supertest';
import { createRouter } from './router';
import { Logger } from 'winston';
const listEndpointName = '/list';
const fileEndpointName = '/file';
const makeBufferFromString = (string: string) => async () =>
Buffer.from(string);
const testingUrlFakeFileTree: ReadTreeResponseFile[] = [
{
path: 'folder/testFile001.txt',
content: makeBufferFromString('folder/testFile001.txt content'),
},
{
path: 'testFile001.txt',
content: makeBufferFromString('testFile002.txt content'),
},
{
path: 'testFile002.txt',
content: makeBufferFromString('testFile001.txt content'),
},
];
const makeFileContent = async (fileContent: string) => {
const result: ReadUrlResponse = {
buffer: makeBufferFromString(fileContent),
};
return result;
};
const testFileOneContent = 'testFileOne content';
const testFileTwoContent = 'testFileTwo content';
const genericFileContent = 'file content';
const mockUrlReader: UrlReader = {
readUrl(url: string) {
switch (url) {
case 'testFileOne':
return makeFileContent(testFileOneContent);
case 'testFileTwo':
return makeFileContent(testFileTwoContent);
default:
return makeFileContent(genericFileContent);
}
},
readTree() {
const result: ReadTreeResponse = {
files: async () => testingUrlFakeFileTree,
archive() {
throw new Error('Function not implemented.');
},
dir() {
throw new Error('Function not implemented.');
},
etag: '',
};
const resultPromise = async () => result;
return resultPromise();
},
search() {
throw new Error('search not implemented.');
},
};
class MockCacheClient implements CacheClient {
private itemRegistry: { [key: string]: any };
constructor() {
this.itemRegistry = {};
}
async get(key: string) {
return this.itemRegistry[key];
}
async set(key: string, value: any) {
this.itemRegistry[key] = value;
}
async delete(key: string) {
delete this.itemRegistry[key];
}
}
describe('createRouter', () => {
let app: express.Express;
beforeEach(async () => {
jest.resetAllMocks();
const router = await createRouter({
reader: mockUrlReader,
cacheClient: new MockCacheClient(),
logger: {
error: (message: any) => message,
} as Logger,
});
app = express().use(router);
});
describe(`GET ${listEndpointName}`, () => {
it('returns bad request (400) when no url is provided', async () => {
const urlNotSpecifiedRequest = await request(app).get(listEndpointName);
const urlNotSpecifiedStatus = urlNotSpecifiedRequest.status;
const urlNotSpecifiedMessage = urlNotSpecifiedRequest.body.message;
const urlNotFilledRequest = await request(app).get(
`${listEndpointName}?url=`,
);
const urlNotFilledStatus = urlNotFilledRequest.status;
const urlNotFilledMessage = urlNotFilledRequest.body.message;
const expectedStatusCode = 400;
const expectedErrorMessage = 'No URL provided';
expect(urlNotSpecifiedStatus).toBe(expectedStatusCode);
expect(urlNotSpecifiedMessage).toBe(expectedErrorMessage);
expect(urlNotFilledStatus).toBe(expectedStatusCode);
expect(urlNotFilledMessage).toBe(expectedErrorMessage);
});
it('returns the correct listing when reading a url', async () => {
const result = await request(app).get(`${listEndpointName}?url=testing`);
const { status, body, error } = result;
const expectedStatusCode = 200;
const expectedBody = {
data: [
{
type: 'file',
name: 'testFile001.txt',
path: 'folder/testFile001.txt',
},
{
type: 'file',
name: 'testFile001.txt',
path: 'testFile001.txt',
},
{
type: 'file',
name: 'testFile002.txt',
path: 'testFile002.txt',
},
],
};
expect(error).toBeFalsy();
expect(status).toBe(expectedStatusCode);
expect(body).toEqual(expectedBody);
});
});
describe(`GET ${fileEndpointName}`, () => {
it('returns bad request (400) when no url is provided', async () => {
const urlNotSpecifiedRequest = await request(app).get(fileEndpointName);
const urlNotSpecifiedStatus = urlNotSpecifiedRequest.status;
const urlNotSpecifiedMessage = urlNotSpecifiedRequest.body.message;
const urlNotFilledRequest = await request(app).get(
`${fileEndpointName}?url=`,
);
const urlNotFilledStatus = urlNotFilledRequest.status;
const urlNotFilledMessage = urlNotFilledRequest.body.message;
const expectedStatusCode = 400;
const expectedErrorMessage = 'No URL provided';
expect(urlNotSpecifiedStatus).toBe(expectedStatusCode);
expect(urlNotSpecifiedMessage).toBe(expectedErrorMessage);
expect(urlNotFilledStatus).toBe(expectedStatusCode);
expect(urlNotFilledMessage).toBe(expectedErrorMessage);
});
it('returns the correct file contents when reading a url', async () => {
const fileOneResponse = await request(app).get(
`${fileEndpointName}?url=testFileOne`,
);
const fileOneStatus = fileOneResponse.status;
const fileOneBody = fileOneResponse.body;
const fileOneError = fileOneResponse.error;
const fileTwoResponse = await request(app).get(
`${fileEndpointName}?url=testFileTwo`,
);
const fileTwoStatus = fileTwoResponse.status;
const fileTwoBody = fileTwoResponse.body;
const fileTwoError = fileTwoResponse.error;
const expectedStatusCode = 200;
expect(fileOneError).toBeFalsy();
expect(fileOneStatus).toBe(expectedStatusCode);
expect(fileOneBody.data).toBe(testFileOneContent);
expect(fileTwoError).toBeFalsy();
expect(fileTwoStatus).toBe(expectedStatusCode);
expect(fileTwoBody.data).toBe(testFileTwoContent);
});
});
});
+129
View File
@@ -0,0 +1,129 @@
/*
* Copyright 2022 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { CacheClient, UrlReader } from '@backstage/backend-common';
import { NotModifiedError, stringifyError } from '@backstage/errors';
import { Logger } from 'winston';
import express from 'express';
import Router from 'express-promise-router';
/** @public */
export type AdrRouterOptions = {
reader: UrlReader;
cacheClient: CacheClient;
logger: Logger;
};
/** @public */
export async function createRouter(
options: AdrRouterOptions,
): Promise<express.Router> {
const { reader, cacheClient, logger } = options;
const router = Router();
router.use(express.json());
router.get('/list', async (req, res) => {
const urlToProcess = req.query.url as string;
if (!urlToProcess) {
res.statusCode = 400;
res.json({ message: 'No URL provided' });
return;
}
const cachedTree = (await cacheClient.get(urlToProcess)) as {
data: {
type: string;
name: string;
path: string;
}[];
etag: string;
};
const cachedData = cachedTree?.data;
try {
const treeGetResponse = await reader.readTree(urlToProcess, {
etag: cachedTree?.etag,
});
const files = await treeGetResponse.files();
const data = files.map(file => {
return {
type: 'file',
name: file.path.substring(file.path.lastIndexOf('/') + 1),
path: file.path,
};
});
await cacheClient.set(urlToProcess, {
data,
etag: treeGetResponse.etag,
});
res.json({ data });
} catch (error: any) {
if (cachedData && error.name === NotModifiedError.name) {
res.json({ data: cachedData });
return;
}
const message = stringifyError(error);
logger.error(`Unable to fetch ADRs from ${urlToProcess}: ${message}`);
res.statusCode = 500;
res.json({ message });
}
});
router.get('/file', async (req, res) => {
const urlToProcess = req.query.url as string;
if (!urlToProcess) {
res.statusCode = 400;
res.json({ message: 'No URL provided' });
return;
}
const cachedFileContent = (await cacheClient.get(urlToProcess)) as {
data: string;
etag: string;
};
try {
const fileGetResponse = await reader.readUrl(urlToProcess, {
etag: cachedFileContent?.etag,
});
const fileBuffer = await fileGetResponse.buffer();
const data = fileBuffer.toString();
await cacheClient.set(urlToProcess, {
data,
etag: fileGetResponse.etag,
});
res.json({ data });
} catch (error) {
if (cachedFileContent && error.name === NotModifiedError.name) {
res.json({ data: cachedFileContent.data });
return;
}
const message = stringifyError(error);
logger.error(`Unable to fetch ADRs from ${urlToProcess}: ${message}`);
res.statusCode = 500;
res.json({ message });
}
});
return router;
}
+6 -4
View File
@@ -4,17 +4,19 @@ Welcome to the ADR plugin!
This plugin allows you to browse ADRs associated with your entities as well as a way to discover ADRs across others entities via Backstage Search. Use this to learn from the past experience of other projects to guide your own architecture decisions.
NOTE: This plugin currently only supports entities/ADRs registered via GitHub integration.
## Setup
Install this plugin:
1. Install this plugin:
```bash
# From your Backstage root directory
yarn --cwd packages/app add @backstage/plugin-adr
```
2. Make sure the [ADR backend plugin](../adr-backend/README.md) is installed.
3. [Configure integrations](https://backstage.io/docs/integrations/) for all sites you would like to pull ADRs from.
### Entity Pages
1. Add the plugin as a tab to your Entity pages:
@@ -79,7 +81,7 @@ case 'adr':
## Custom ADR formats
By default, this plugin will parse ADRs according to the format specified by the [Markdown Architecture Decision Record (MADR)](https://adr.github.io/madr/) template. If your ADRs are written using a different format, you can apply the following customizations to correctly identify and parse your documents:
By default, this plugin will parse ADRs according to the format specified by the [Markdown Architecture Decision Record (MADR) v2.x template](https://github.com/adr/madr/tree/2.1.2). If your ADRs are written using a different format, you can apply the following customizations to correctly identify and parse your documents:
### Custom Filename/Path Format
+43
View File
@@ -7,11 +7,37 @@
import { AdrDocument } from '@backstage/plugin-adr-common';
import { AdrFilePathFilterFn } from '@backstage/plugin-adr-common';
import { ApiRef } from '@backstage/core-plugin-api';
import { BackstagePlugin } from '@backstage/core-plugin-api';
import { DiscoveryApi } from '@backstage/core-plugin-api';
import { isAdrAvailable } from '@backstage/plugin-adr-common';
import { ResultHighlight } from '@backstage/plugin-search-common';
import { RouteRef } from '@backstage/core-plugin-api';
// @public
export interface AdrApi {
listAdrs(url: string): Promise<AdrListResult>;
readAdr(url: string): Promise<AdrReadResult>;
}
// @public
export const adrApiRef: ApiRef<AdrApi>;
// @public
export class AdrClient implements AdrApi {
constructor(options: AdrClientOptions);
// (undocumented)
listAdrs(url: string): Promise<AdrListResult>;
// (undocumented)
readAdr(url: string): Promise<AdrReadResult>;
}
// @public
export interface AdrClientOptions {
// (undocumented)
discoveryApi: DiscoveryApi;
}
// @public
export type AdrContentDecorator = (adrInfo: {
baseUrl: string;
@@ -20,6 +46,18 @@ export type AdrContentDecorator = (adrInfo: {
content: string;
};
// @public
export type AdrFileInfo = {
type: string;
path: string;
name: string;
};
// @public
export type AdrListResult = {
data: AdrFileInfo[];
};
// @public
export const adrPlugin: BackstagePlugin<
{
@@ -38,6 +76,11 @@ export const AdrReader: {
}>;
};
// @public
export type AdrReadResult = {
data: string;
};
// @public
export function AdrSearchResultListItem(props: {
lineClamp?: number;
-2
View File
@@ -34,8 +34,6 @@
"@material-ui/core": "^4.12.2",
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "4.0.0-alpha.57",
"git-url-parse": "^13.0.0",
"octokit": "^2.0.0",
"react-markdown": "^8.0.0",
"react-use": "^17.2.4",
"remark-gfm": "^3.0.1"
+66
View File
@@ -0,0 +1,66 @@
/*
* Copyright 2022 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { DiscoveryApi } from '@backstage/core-plugin-api';
import { AdrApi, AdrListResult, AdrReadResult } from './types';
/**
* Options for creating an AdrClient.
*
* @public
*/
export interface AdrClientOptions {
discoveryApi: DiscoveryApi;
}
const readEndpoint = 'file';
const listEndpoint = 'list';
/**
* An implementation of the AdrApi that communicates with the ADR backend plugin.
*
* @public
*/
export class AdrClient implements AdrApi {
private readonly discoveryApi: DiscoveryApi;
constructor(options: AdrClientOptions) {
this.discoveryApi = options.discoveryApi;
}
private async fetchAdrApi<T>(endpoint: string, fileUrl: string): Promise<T> {
const baseUrl = await this.discoveryApi.getBaseUrl('adr');
const targetUrl = `${baseUrl}/${endpoint}?url=${encodeURIComponent(
fileUrl,
)}`;
const result = await fetch(targetUrl);
const data = await result.json();
if (!result.ok) {
throw new Error(`${data.message}`);
}
return data;
}
async listAdrs(url: string): Promise<AdrListResult> {
return this.fetchAdrApi<AdrListResult>(listEndpoint, url);
}
async readAdr(url: string): Promise<AdrReadResult> {
return this.fetchAdrApi<AdrReadResult>(readEndpoint, url);
}
}
+25
View File
@@ -0,0 +1,25 @@
/*
* Copyright 2022 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { AdrClient } from './AdrClient';
export type { AdrClientOptions } from './AdrClient';
export { adrApiRef } from './types';
export type {
AdrApi,
AdrFileInfo,
AdrListResult,
AdrReadResult,
} from './types';
+74
View File
@@ -0,0 +1,74 @@
/*
* Copyright 2022 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { createApiRef } from '@backstage/core-plugin-api';
/**
* Contains information about an ADR file.
*
* @public
*/
export type AdrFileInfo = {
/** The file type. */
type: string;
/** The relative path of the ADR file. */
path: string;
/** The name of the ADR file. */
name: string;
};
/**
* The result of listing ADRs.
*
* @public
*/
export type AdrListResult = {
data: AdrFileInfo[];
};
/**
* The result of reading an ADR.
*
* @public
*/
export type AdrReadResult = {
/** The contents of the read ADR file. */
data: string;
};
/**
* The API used by the adr plugin to list and read ADRs.
*
* @public
*/
export interface AdrApi {
/** Lists the ADRs at the provided url. */
listAdrs(url: string): Promise<AdrListResult>;
/** Reads the contents of the ADR at the provided url. */
readAdr(url: string): Promise<AdrReadResult>;
}
/**
* ApiRef for the AdrApi.
*
* @public
*/
export const adrApiRef = createApiRef<AdrApi>({
id: 'plugin.adr.api',
});
@@ -26,9 +26,10 @@ import { scmIntegrationsApiRef } from '@backstage/integration-react';
import { getAdrLocationUrl } from '@backstage/plugin-adr-common';
import { useEntity } from '@backstage/plugin-catalog-react';
import { useOctokitRequest } from '../../hooks';
import { adrDecoratorFactories } from './decorators';
import { AdrContentDecorator } from './types';
import { adrApiRef } from '../../api';
import useAsync from 'react-use/lib/useAsync';
/**
* Component to fetch and render an ADR.
@@ -42,10 +43,13 @@ export const AdrReader = (props: {
const { adr, decorators } = props;
const { entity } = useEntity();
const scmIntegrations = useApi(scmIntegrationsApiRef);
const adrApi = useApi(adrApiRef);
const adrLocationUrl = getAdrLocationUrl(entity, scmIntegrations);
const { value, loading, error } = useOctokitRequest(
`${adrLocationUrl.replace(/\/$/, '')}/${adr}`,
const url = `${adrLocationUrl.replace(/\/$/, '')}/${adr}`;
const { value, loading, error } = useAsync(
async () => adrApi.readAdr(url),
[url],
);
const adrContent = useMemo(() => {
@@ -44,9 +44,10 @@ import {
Typography,
} from '@material-ui/core';
import { useOctokitRequest } from '../../hooks';
import { rootRouteRef } from '../../routes';
import { AdrContentDecorator, AdrReader } from '../AdrReader';
import { adrApiRef } from '../../api';
import useAsync from 'react-use/lib/useAsync';
const useStyles = makeStyles((theme: Theme) => ({
adrMenu: {
@@ -69,10 +70,13 @@ export const EntityAdrContent = (props: {
const [adrList, setAdrList] = useState<string[]>([]);
const [searchParams, setSearchParams] = useSearchParams();
const scmIntegrations = useApi(scmIntegrationsApiRef);
const adrApi = useApi(adrApiRef);
const entityHasAdrs = isAdrAvailable(entity);
const { value, loading, error } = useOctokitRequest(
getAdrLocationUrl(entity, scmIntegrations),
const url = getAdrLocationUrl(entity, scmIntegrations);
const { value, loading, error } = useAsync(
async () => adrApi.listAdrs(url),
[url],
);
const selectedAdr =
@@ -1,59 +0,0 @@
/*
* Copyright 2022 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import parseGitUrl from 'git-url-parse';
import useAsync from 'react-use/lib/useAsync';
import { Octokit } from 'octokit';
import { useApi } from '@backstage/core-plugin-api';
import {
scmAuthApiRef,
scmIntegrationsApiRef,
} from '@backstage/integration-react';
/**
* Hook for triggering authenticated Octokit requests against the GitHub Content API
* @public
*/
export const useOctokitRequest = (request: string): any => {
const authApi = useApi(scmAuthApiRef);
const scmIntegrations = useApi(scmIntegrationsApiRef);
const { owner, name, ref, filepath } = parseGitUrl(request);
const path = filepath.replace(/^\//, '');
const baseUrl = scmIntegrations.github.byUrl(request)?.config.apiBaseUrl;
return useAsync<any>(async () => {
const { token } = await authApi.getCredentials({
url: request,
additionalScope: {
customScopes: {
github: ['repo'],
},
},
});
const octokit = new Octokit({
auth: token,
baseUrl,
});
return octokit.request(
`GET /repos/${owner}/${name}/contents/${path}?ref=${ref}`,
{
headers: { Accept: 'application/vnd.github.v3.raw' },
},
);
}, [request]);
};
+10
View File
@@ -13,11 +13,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* ADR frontend plugin
*
* @packageDocumentation
*/
export { adrApiRef, AdrClient } from './api';
export type {
AdrApi,
AdrClientOptions,
AdrFileInfo,
AdrListResult,
AdrReadResult,
} from './api';
export { isAdrAvailable } from '@backstage/plugin-adr-common';
export * from './components/AdrReader';
export { adrPlugin, EntityAdrContent } from './plugin';
+14 -1
View File
@@ -14,11 +14,13 @@
* limitations under the License.
*/
import { adrApiRef, AdrClient } from './api';
import {
createApiFactory,
createPlugin,
createRoutableExtension,
discoveryApiRef,
} from '@backstage/core-plugin-api';
import { rootRouteRef } from './routes';
/**
@@ -27,6 +29,17 @@ import { rootRouteRef } from './routes';
*/
export const adrPlugin = createPlugin({
id: 'adr',
apis: [
createApiFactory({
api: adrApiRef,
deps: {
discoveryApi: discoveryApiRef,
},
factory({ discoveryApi }) {
return new AdrClient({ discoveryApi });
},
}),
],
routes: {
root: rootRouteRef,
},
@@ -23,6 +23,7 @@ import { appPlugin } from './appPlugin';
import {
databaseFactory,
httpRouterFactory,
rootHttpRouterFactory,
loggerFactory,
rootLoggerFactory,
} from '@backstage/backend-app-api';
@@ -63,6 +64,7 @@ describe('appPlugin', () => {
rootLoggerFactory(),
databaseFactory(),
httpRouterFactory(),
rootHttpRouterFactory(),
],
features: [
appPlugin({
+1 -1
View File
@@ -18,9 +18,9 @@ import express from 'express';
import {
coreServices,
createBackendPlugin,
loggerToWinstonLogger,
} from '@backstage/backend-plugin-api';
import { createRouter } from './router';
import { loggerToWinstonLogger } from '@backstage/backend-common';
/** @alpha */
export type AppPluginOptions = {
+1 -1
View File
@@ -7,7 +7,7 @@
import { BackstageIdentityResponse } from '@backstage/plugin-auth-node';
import { BackstageSignInResult } from '@backstage/plugin-auth-node';
import { CacheClient } from '@backstage/backend-common';
import { CacheClient } from '@backstage/backend-plugin-api';
import { CatalogApi } from '@backstage/catalog-client';
import { Config } from '@backstage/config';
import { Entity } from '@backstage/catalog-model';
+1 -1
View File
@@ -34,7 +34,7 @@
"@backstage/cli": "workspace:^",
"@openapitools/openapi-generator-cli": "^2.4.26",
"msw": "^0.49.0",
"ts-morph": "^15.0.0"
"ts-morph": "^17.0.0"
},
"files": [
"dist"
@@ -14,10 +14,10 @@
* limitations under the License.
*/
import { loggerToWinstonLogger } from '@backstage/backend-common';
import {
coreServices,
createBackendModule,
loggerToWinstonLogger,
} from '@backstage/backend-plugin-api';
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node';
import { AwsS3EntityProvider } from '../providers';

Some files were not shown because too many files have changed in this diff Show More