diff --git a/.changeset/bright-plants-travel.md b/.changeset/bright-plants-travel.md deleted file mode 100644 index ad8a77d17b..0000000000 --- a/.changeset/bright-plants-travel.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-kubernetes': patch ---- - -The Kubernetes plugin will now re-fetch the kubernetes objects every ten seconds (not current configurable), this allows users to track the progress of deployments without refreshing the browser. diff --git a/.changeset/cold-wolves-eat.md b/.changeset/cold-wolves-eat.md deleted file mode 100644 index fa3a2180b2..0000000000 --- a/.changeset/cold-wolves-eat.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-sentry': patch ---- - -feature: sentry-plugin allows passing search query for listing issues diff --git a/.changeset/dirty-bugs-care.md b/.changeset/dirty-bugs-care.md deleted file mode 100644 index 4d90a9c939..0000000000 --- a/.changeset/dirty-bugs-care.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@backstage/test-utils': patch -'@backstage/test-utils-core': patch ---- - -Migrates all utility methods from `test-utils-core` into `test-utils` and delete exports from the old package. -This should have no impact since this package is considered internal and have no usages outside core packages. - -Notable changes are that the testing tool `msw.setupDefaultHandlers()` have been deprecated in favour of `setupRequestMockHandlers()`. diff --git a/.changeset/dull-news-visit.md b/.changeset/dull-news-visit.md deleted file mode 100644 index e1fab41ebf..0000000000 --- a/.changeset/dull-news-visit.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-techdocs': patch ---- - -Reader will now scroll to the top of the page when navigating between pages diff --git a/.changeset/friendly-olives-drop.md b/.changeset/friendly-olives-drop.md deleted file mode 100644 index 371cf0e4db..0000000000 --- a/.changeset/friendly-olives-drop.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder': patch ---- - -Surfacing all components of the ScaffolderPage outside of the plugin so you can customize the page diff --git a/.changeset/green-parrots-thank.md b/.changeset/green-parrots-thank.md deleted file mode 100644 index 9296a5119a..0000000000 --- a/.changeset/green-parrots-thank.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@backstage/plugin-azure-devops': patch ---- - -Azure DevOps frontend refactoring items from issue #7641 - -- Remove backend setup documentation and linked to the Azure DevOps backend plugin for these instructions -- Improved documentation to be easier to expand with new features in the future -- Removed Router based on feedback from maintainers -- Added tests for `getBuildResultComponent` and `getBuildStateComponent` from the BuildTable diff --git a/.changeset/green-tips-eat.md b/.changeset/green-tips-eat.md deleted file mode 100644 index b8c631fbf4..0000000000 --- a/.changeset/green-tips-eat.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder': patch ---- - -Scaffolder: Enable back Template action buttons if template fails to execute diff --git a/.changeset/kind-islands-attack.md b/.changeset/kind-islands-attack.md deleted file mode 100644 index a549839bc7..0000000000 --- a/.changeset/kind-islands-attack.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-azure-devops-backend': patch ---- - -Added duration (startTime and finishTime) and identity (uniqueName) to the RepoBuild results. Also did a bit of refactoring to help finish up the backend items in issue #7641 diff --git a/.changeset/popular-apples-sparkle.md b/.changeset/popular-apples-sparkle.md deleted file mode 100644 index b8437795da..0000000000 --- a/.changeset/popular-apples-sparkle.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -'@backstage/backend-common': patch -'@backstage/catalog-model': patch -'@backstage/cli': patch -'@backstage/config-loader': patch -'@backstage/core-app-api': patch -'@backstage/errors': patch -'@backstage/search-common': patch -'@backstage/test-utils': patch -'@backstage/plugin-app-backend': patch -'@backstage/plugin-catalog-backend': patch -'@backstage/plugin-catalog-backend-module-ldap': patch -'@backstage/plugin-catalog-graphql': patch -'@backstage/plugin-catalog-react': patch -'@backstage/plugin-config-schema': patch -'@backstage/plugin-scaffolder': patch -'@backstage/plugin-scaffolder-backend': patch -'@backstage/plugin-scaffolder-backend-module-cookiecutter': patch -'@backstage/plugin-scaffolder-backend-module-rails': patch -'@backstage/plugin-scaffolder-backend-module-yeoman': patch -'@backstage/plugin-scaffolder-common': patch -'@backstage/plugin-search': patch -'@backstage/plugin-shortcuts': patch ---- - -Switch to use the json and observable types from `@backstage/types` diff --git a/.changeset/quick-walls-know.md b/.changeset/quick-walls-know.md deleted file mode 100644 index 14dd78364f..0000000000 --- a/.changeset/quick-walls-know.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/techdocs-common': patch ---- - -Support optional bucketRootPath configuration parameter in S3 and GCS publishers diff --git a/.changeset/rotten-melons-carry.md b/.changeset/rotten-melons-carry.md deleted file mode 100644 index 2f1429c399..0000000000 --- a/.changeset/rotten-melons-carry.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@backstage/config': patch -'@backstage/core-app-api': patch -'@backstage/core-plugin-api': patch -'@backstage/plugin-scaffolder-backend': patch ---- - -Start using the new `@backstage/types` package. Initially, this means using the `Observable` and `Json*` types from there. The types also remain in their old places but deprecated, and will be removed in a future release. diff --git a/.changeset/rude-starfishes-walk.md b/.changeset/rude-starfishes-walk.md deleted file mode 100644 index 87ec76fd0a..0000000000 --- a/.changeset/rude-starfishes-walk.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/config': patch -'@backstage/core-app-api': patch -'@backstage/core-plugin-api': patch ---- - -Replace usage of test-utils-core with test-utils diff --git a/.changeset/search-spicy-foxes-joke.md b/.changeset/search-spicy-foxes-joke.md deleted file mode 100644 index c1ed318f6d..0000000000 --- a/.changeset/search-spicy-foxes-joke.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-search-backend-node': patch ---- - -Handle special case when filter array has single value optimizing Lunr search behaviour. diff --git a/.changeset/tough-avocados-give.md b/.changeset/tough-avocados-give.md deleted file mode 100644 index 08b8a7ea72..0000000000 --- a/.changeset/tough-avocados-give.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-sentry': patch ---- - -fix: sentry-plugin correction for allowed period values diff --git a/.changeset/unlucky-hotels-roll.md b/.changeset/unlucky-hotels-roll.md deleted file mode 100644 index 0ba616c2c3..0000000000 --- a/.changeset/unlucky-hotels-roll.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-components': patch ---- - -Deprecated `DismissbleBannerClassKey` and fixed the typo to make `DismissableBannerClassKey` diff --git a/.changeset/wet-socks-grow.md b/.changeset/wet-socks-grow.md deleted file mode 100644 index 8ccbb7a2a2..0000000000 --- a/.changeset/wet-socks-grow.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/errors': patch ---- - -Add `stringifyError` that is useful for logging e.g. `Something went wrong, ${stringifyError(e)}` diff --git a/.github/workflows/e2e-win.yml b/.github/workflows/e2e-win.yml index f39a89e8c6..acaf4e189e 100644 --- a/.github/workflows/e2e-win.yml +++ b/.github/workflows/e2e-win.yml @@ -7,7 +7,7 @@ on: paths: - '.github/workflows/e2e-win.yml' - 'packages/cli/**' - - 'packages/e2e/**' + - 'packages/e2e-test/**' - 'packages/create-app/**' jobs: @@ -21,7 +21,7 @@ jobs: env: CI: true - NODE_OPTIONS: --max-old-space-size=4096 + NODE_OPTIONS: --max-old-space-size=8192 name: Node ${{ matrix.node-version }} on ${{ matrix.os }} steps: @@ -48,3 +48,5 @@ jobs: run: yarn build --ignore example-app --ignore example-backend --ignore @techdocs/cli - name: run E2E test run: yarn e2e-test run + env: + DEBUG: zombie diff --git a/ADOPTERS.md b/ADOPTERS.md index db751bfb9b..a2015086c3 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -59,3 +59,6 @@ | [Box](https://www.box.com) | [@kielosz](https://github.com/kielosz), [@jluk-box](https://github.com/jluk-box), [@ptychu](https://github.com/ptychu), [@alexrybch](https://github.com/alexrybch), [@szubster](https://github.com/szubster) | Developer portal for service catalog, integration with internal systems, new service onboarding. | | [Bazaarvoice](https://www.bazaarvoice.com) | [@niallmccullagh](https://github.com/niallmccullagh) | Developer portal for service catalog and scaffolds, publishing Github docs and API documentation, visualising our internal tech radar and our product engineering org structure. | | [Krateo PlatformOps](https://www.krateo.io) | [@projectkerberus](https://github.com/projectkerberus) | A multi-cloud control plane to create, manage and deploy any kind of resource easily and centrally via a Developer Portal that centralizes via a self-service catalog the templating and ownership of services, the available documentation, the overview of the components that compose an entire domain and all the data of the service lifecycle. | +| [Adevinta](https://www.adevinta.com) | [Ray Sinnema](https://github.com/RemonSinnema) | Showcase shared services to our internal customers. | +| [Splunk](https://www.splunk.com) | [@tonytamsf](https://github.com/tonytamsf) | Developer portal as a centralized place to find people, services, documentation, escalation policies and give bravos. This portal is also being used as a centralized search engine for engineering specific documentation.| +| [SoundCloud](https://www.soundcloud.com) | [Julio Zynger](https://github.com/julioz) | Developer portal as a [humane registry](https://martinfowler.com/bliki/HumaneRegistry.html) for the organization: catalog of people, services, documentation, feature toggles, escalation policies, etc.| diff --git a/README.md b/README.md index 1078631926..13b7c945cf 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ # [Backstage](https://backstage.io) +> 🏖 All of the maintainers will be taking a wellness break Nov. 1–5. The repo and Discord may be quieter than usual, but not to worry. We’ll have coverage plans in place and be back in full force, rested and restored, on Nov. 8. 🏖 + [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![CNCF Status](https://img.shields.io/badge/cncf%20status-sandbox-blue.svg)](https://www.cncf.io/projects) [![Main CI Build](https://github.com/backstage/backstage/workflows/Main%20Master%20Build/badge.svg)](https://github.com/backstage/backstage/actions?query=workflow%3A%22Main+Master+Build%22) diff --git a/docs/features/software-templates/writing-custom-actions.md b/docs/features/software-templates/writing-custom-actions.md index 581a974455..07c4891a6c 100644 --- a/docs/features/software-templates/writing-custom-actions.md +++ b/docs/features/software-templates/writing-custom-actions.md @@ -156,4 +156,16 @@ return await createRouter({ }); ``` +### List of custom action packages + +Here is a list of Open Source custom actions that you can add to your Backstage +scaffolder backend: + +| Name | Package | Owner | +| ------------- | --------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------- | +| Yeoman | [plugin-scaffolder-backend-module-yeoman](https://www.npmjs.com/package/@backstage/plugin-scaffolder-backend-module-yeoman) | [Backstage](https://backstage.io) | +| Cookiecutter | [plugin-scaffolder-backend-module-cookiecutter](https://www.npmjs.com/package/@backstage/plugin-scaffolder-backend-module-cookiecutter) | [Backstage](https://backstage.io) | +| Rails | [plugin-scaffolder-backend-module-rails](https://www.npmjs.com/package/@backstage/plugin-scaffolder-backend-module-rails) | [Backstage](https://backstage.io) | +| HTTP requests | [scaffolder-backend-module-http-request](https://www.npmjs.com/package/@roadiehq/scaffolder-backend-module-http-request) | [Roadie](https://roadie.io) | + Have fun! 🚀 diff --git a/docs/features/software-templates/writing-custom-field-extensions.md b/docs/features/software-templates/writing-custom-field-extensions.md index 4f2d3bdf5d..ebb7af4398 100644 --- a/docs/features/software-templates/writing-custom-field-extensions.md +++ b/docs/features/software-templates/writing-custom-field-extensions.md @@ -27,20 +27,27 @@ You can create your own Field Extension by using the ```tsx //packages/app/scaffolder/MyCustomExtension/MyCustomExtension.tsx +import React from 'react'; import { FieldProps, FieldValidation } from '@rjsf/core'; +import FormControl from '@material-ui/core/FormControl'; import { KubernetesValidatorFunctions } from '@backstage/catalog-model'; /* This is the actual component that will get rendered in the form */ -export const MyCustomExtension = ({ onChange, required }: FieldProps) => { +export const MyCustomExtension = ({ + onChange, + rawErrors, + required, + formData, +}: FieldProps) => { return ( - 0 && !formData} onChange={onChange} - > - ) + /> + ); }; /* @@ -63,10 +70,10 @@ export const myCustomValidation = ( ```tsx // packages/app/scaffolder/MyCustomExtension/extensions.ts -/* +/* This is where the magic happens and creates the custom field extension. - Note that if you're writing extensions part of a separate plugin, + Note that if you're writing extensions part of a separate plugin, then please use `plugin.provide` from there instead and export it part of your `plugin.ts` rather than re-using the `scaffolder.plugin`. */ diff --git a/package.json b/package.json index 4aa6905085..f5d20fd39d 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,6 @@ }, "resolutions": { "**/@graphql-codegen/cli/**/ws": "^7.4.6", - "**/@roadiehq/**/@backstage/core": "*", "**/@roadiehq/**/@backstage/plugin-catalog": "*", "**/@roadiehq/**/@backstage/catalog-model": "*", "graphql-language-service-interface": "2.8.2", diff --git a/packages/backend-common/CHANGELOG.md b/packages/backend-common/CHANGELOG.md index 131b160a36..f0368b55d4 100644 --- a/packages/backend-common/CHANGELOG.md +++ b/packages/backend-common/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/backend-common +## 0.9.8 + +### Patch Changes + +- 96cfa561eb: Adjusted some API exports +- 10615525f3: Switch to use the json and observable types from `@backstage/types` +- 1be8d2abdb: Any set configurations which have been tagged with a visibility 'secret', are now redacted from log lines. +- Updated dependencies + - @backstage/config@0.1.11 + - @backstage/cli-common@0.1.5 + - @backstage/errors@0.1.4 + - @backstage/integration@0.6.9 + - @backstage/config-loader@0.7.1 + ## 0.9.7 ### Patch Changes diff --git a/packages/backend-common/api-report.md b/packages/backend-common/api-report.md index 2336a57ec3..a19447034e 100644 --- a/packages/backend-common/api-report.md +++ b/packages/backend-common/api-report.md @@ -211,6 +211,12 @@ export type ErrorHandlerOptions = { logClientErrors?: boolean; }; +// @public +export type FromReadableArrayOptions = Array<{ + data: Readable; + path: string; +}>; + // @public (undocumented) export function getRootLogger(): winston.Logger; @@ -419,15 +425,13 @@ export type ReadTreeResponse = { etag: string; }; -// @public (undocumented) +// @public export type ReadTreeResponseDirOptions = { targetDir?: string; }; // @public (undocumented) export interface ReadTreeResponseFactory { - // Warning: (ae-forgotten-export) The symbol "FromReadableArrayOptions" needs to be exported by the entry point index.d.ts - // // (undocumented) fromReadableArray( options: FromReadableArrayOptions, @@ -442,7 +446,7 @@ export interface ReadTreeResponseFactory { ): Promise; } -// @public (undocumented) +// @public export type ReadTreeResponseFactoryOptions = { stream: Readable; subpath?: string; @@ -580,7 +584,7 @@ export type UrlReader = { search(url: string, options?: SearchOptions): Promise; }; -// @public (undocumented) +// @public export type UrlReaderPredicateTuple = { predicate: (url: URL) => boolean; reader: UrlReader; diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index 60824f0c40..a174862b4a 100644 --- a/packages/backend-common/package.json +++ b/packages/backend-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-common", "description": "Common functionality library for Backstage backends", - "version": "0.9.7", + "version": "0.9.8", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -29,13 +29,14 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/cli-common": "^0.1.4", - "@backstage/config": "^0.1.10", - "@backstage/config-loader": "^0.7.0", - "@backstage/errors": "^0.1.3", - "@backstage/integration": "^0.6.7", + "@backstage/cli-common": "^0.1.5", + "@backstage/config": "^0.1.11", + "@backstage/config-loader": "^0.7.1", + "@backstage/errors": "^0.1.4", + "@backstage/integration": "^0.6.9", "@backstage/types": "^0.1.1", "@google-cloud/storage": "^5.8.0", + "@lerna/project": "^4.0.0", "@octokit/rest": "^18.5.3", "@types/cors": "^2.8.6", "@types/dockerode": "^3.2.1", @@ -78,8 +79,8 @@ } }, "devDependencies": { - "@backstage/cli": "^0.8.0", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.1", + "@backstage/test-utils": "^0.1.20", "@types/archiver": "^5.1.0", "@types/compression": "^1.7.0", "@types/concat-stream": "^1.6.0", @@ -99,7 +100,7 @@ "http-errors": "^1.7.3", "jest": "^26.0.1", "mock-fs": "^5.1.0", - "msw": "^0.29.0", + "msw": "^0.35.0", "mysql2": "^2.2.5", "recursive-readdir": "^2.2.2", "supertest": "^6.1.3" diff --git a/packages/backend-common/src/config.ts b/packages/backend-common/src/config.ts index 9b0eb8dcd0..3c5a2d7b26 100644 --- a/packages/backend-common/src/config.ts +++ b/packages/backend-common/src/config.ts @@ -18,11 +18,42 @@ import { resolve as resolvePath } from 'path'; import parseArgs from 'minimist'; import { Logger } from 'winston'; import { findPaths } from '@backstage/cli-common'; -import { Config, ConfigReader } from '@backstage/config'; +import { + loadConfigSchema, + loadConfig, + ConfigSchema, + ConfigTarget +} from '@backstage/config-loader'; +import { AppConfig, Config, ConfigReader } from '@backstage/config'; import { JsonValue } from '@backstage/types'; -import { ConfigTarget, loadConfig } from '@backstage/config-loader'; + import { isValidUrl } from './urls'; +import { setRootLoggerRedactionList } from './logging/rootLogger'; + +// Fetch the schema and get all the secrets to pass to the rootLogger for redaction +const updateRedactionList = ( + schema: ConfigSchema, + configs: AppConfig[], + logger: Logger, +) => { + const secretAppConfigs = schema.process(configs, { visibility: ['secret'] }); + const secretConfig = ConfigReader.fromConfigs(secretAppConfigs); + const values = new Set(); + const data = secretConfig.get(); + + JSON.parse( + JSON.stringify(data), + (_, v) => typeof v === 'string' && values.add(v), + ); + + logger.info( + `${values.size} secrets found in the config which will be redacted`, + ); + + setRootLoggerRedactionList(Array.from(values)); +}; + export class ObservableConfigProxy implements Config { private config: Config = new ConfigReader({}); @@ -155,11 +186,20 @@ export async function loadBackendConfig(options: { .flat() .map(arg => (isValidUrl(arg) ? { url: arg } : { path: resolvePath(arg) })); - const config = new ObservableConfigProxy(options.logger); - /* eslint-disable-next-line no-restricted-syntax */ const paths = findPaths(__dirname); + // TODO(hhogg): This is fetching _all_ of the packages of the monorepo + // in order to find the secrets for redactions, however we only care about + // the backend ones, we need to find a way to exclude the frontend packages. + const { Project } = require('@lerna/project'); + const project = new Project(paths.targetDir); + const packages = await project.getPackages(); + const schema = await loadConfigSchema({ + dependencies: packages.map((p: any) => p.name), + }); + + const config = new ObservableConfigProxy(options.logger); const configs = await loadConfig({ configRoot: paths.targetRoot, configPaths: [], @@ -192,5 +232,9 @@ export async function loadBackendConfig(options: { config.setConfig(ConfigReader.fromConfigs(configs)); + // Subscribe to config changes and update the redaction list for logging + updateRedactionList(schema, configs, options.logger); + config.subscribe(() => updateRedactionList(schema, configs, options.logger)); + return config; } diff --git a/packages/backend-common/src/logging/index.ts b/packages/backend-common/src/logging/index.ts index 71e9618f0c..f50114a9ae 100644 --- a/packages/backend-common/src/logging/index.ts +++ b/packages/backend-common/src/logging/index.ts @@ -15,5 +15,5 @@ */ export * from './formats'; -export * from './rootLogger'; +export { createRootLogger, getRootLogger, setRootLogger } from './rootLogger'; export * from './voidLogger'; diff --git a/packages/backend-common/src/logging/rootLogger.test.ts b/packages/backend-common/src/logging/rootLogger.test.ts index 50cf867c85..192decb653 100644 --- a/packages/backend-common/src/logging/rootLogger.test.ts +++ b/packages/backend-common/src/logging/rootLogger.test.ts @@ -15,7 +15,12 @@ */ import * as winston from 'winston'; -import { createRootLogger, getRootLogger, setRootLogger } from './rootLogger'; +import { + createRootLogger, + getRootLogger, + setRootLogger, + setRootLoggerRedactionList, +} from './rootLogger'; describe('rootLogger', () => { it('can replace the default logger', () => { @@ -30,7 +35,20 @@ describe('rootLogger', () => { ); }); - describe('createRootLoger', () => { + it('redacts given secrets', () => { + const logger = createRootLogger(); + jest.spyOn(logger, 'write'); + setRootLoggerRedactionList(['SECRET-1', 'SECRET_2', 'SECRET.3']); + logger.info('Logging SECRET-1 and SECRET_2 and SECRET.3'); + + expect(logger.write).toHaveBeenCalledWith( + expect.objectContaining({ + message: 'Logging [REDACTED] and [REDACTED] and [REDACTED]', + }), + ); + }); + + describe('createRootLogger', () => { it('creates a new logger', () => { const oldLogger = getRootLogger(); const newLogger = createRootLogger(); diff --git a/packages/backend-common/src/logging/rootLogger.ts b/packages/backend-common/src/logging/rootLogger.ts index d06037863c..b05763a42c 100644 --- a/packages/backend-common/src/logging/rootLogger.ts +++ b/packages/backend-common/src/logging/rootLogger.ts @@ -18,8 +18,10 @@ import { merge } from 'lodash'; import * as winston from 'winston'; import { LoggerOptions } from 'winston'; import { coloredFormat } from './formats'; +import { escapeRegExp } from '../util/escapeRegExp'; let rootLogger: winston.Logger; +let redactionRegExp: RegExp; /** @public */ export function getRootLogger(): winston.Logger { @@ -31,6 +33,30 @@ export function setRootLogger(newLogger: winston.Logger) { rootLogger = newLogger; } +export function setRootLoggerRedactionList(redactionList: string[]) { + if (redactionList.length) { + redactionRegExp = new RegExp( + `(${redactionList.map(escapeRegExp).join('|')})`, + 'g', + ); + } +} + +/** + * A winston formatting function that finds occurrences of filteredKeys + * and replaces them with the corresponding identifier. + */ +function redactLogLine(info: winston.Logform.TransformableInfo) { + // TODO(hhogg): The logger is created before the config is loaded, + // because the logger is needed in the config loader. There is a risk of + // a secret being logged out during the config loading stage. + if (redactionRegExp) { + info.message = info.message.replace(redactionRegExp, '[REDACTED]'); + } + + return info; +} + /** @public */ export function createRootLogger( options: winston.LoggerOptions = {}, @@ -41,6 +67,7 @@ export function createRootLogger( { level: env.LOG_LEVEL || 'info', format: winston.format.combine( + winston.format(redactLogLine)(), env.NODE_ENV === 'production' ? winston.format.json() : coloredFormat, ), defaultMeta: { diff --git a/packages/backend-common/src/reading/AzureUrlReader.test.ts b/packages/backend-common/src/reading/AzureUrlReader.test.ts index 59968a18e9..23de8389ad 100644 --- a/packages/backend-common/src/reading/AzureUrlReader.test.ts +++ b/packages/backend-common/src/reading/AzureUrlReader.test.ts @@ -19,7 +19,7 @@ import { AzureIntegration, readAzureIntegrationConfig, } from '@backstage/integration'; -import { msw } from '@backstage/test-utils'; +import { setupRequestMockHandlers } from '@backstage/test-utils'; import fs from 'fs-extra'; import mockFs from 'mock-fs'; import { rest } from 'msw'; @@ -51,7 +51,7 @@ describe('AzureUrlReader', () => { }); const worker = setupServer(); - msw.setupDefaultHandlers(worker); + setupRequestMockHandlers(worker); describe('read', () => { beforeEach(() => { diff --git a/packages/backend-common/src/reading/BitbucketUrlReader.test.ts b/packages/backend-common/src/reading/BitbucketUrlReader.test.ts index 5bbf3725ea..ea8e4626be 100644 --- a/packages/backend-common/src/reading/BitbucketUrlReader.test.ts +++ b/packages/backend-common/src/reading/BitbucketUrlReader.test.ts @@ -19,7 +19,7 @@ import { BitbucketIntegration, readBitbucketIntegrationConfig, } from '@backstage/integration'; -import { msw } from '@backstage/test-utils'; +import { setupRequestMockHandlers } from '@backstage/test-utils'; import fs from 'fs-extra'; import mockFs from 'mock-fs'; import { rest } from 'msw'; @@ -72,7 +72,7 @@ describe('BitbucketUrlReader', () => { }); const worker = setupServer(); - msw.setupDefaultHandlers(worker); + setupRequestMockHandlers(worker); describe('readUrl', () => { worker.use( diff --git a/packages/backend-common/src/reading/FetchUrlReader.test.ts b/packages/backend-common/src/reading/FetchUrlReader.test.ts index e8c16c5f0a..124abb799c 100644 --- a/packages/backend-common/src/reading/FetchUrlReader.test.ts +++ b/packages/backend-common/src/reading/FetchUrlReader.test.ts @@ -16,7 +16,7 @@ import { ConfigReader } from '@backstage/config'; import { NotFoundError, NotModifiedError } from '@backstage/errors'; -import { msw } from '@backstage/test-utils'; +import { setupRequestMockHandlers } from '@backstage/test-utils'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; import { getVoidLogger } from '../logging'; @@ -28,7 +28,7 @@ const fetchUrlReader = new FetchUrlReader(); describe('FetchUrlReader', () => { const worker = setupServer(); - msw.setupDefaultHandlers(worker); + setupRequestMockHandlers(worker); beforeEach(() => { jest.clearAllMocks(); diff --git a/packages/backend-common/src/reading/GithubUrlReader.test.ts b/packages/backend-common/src/reading/GithubUrlReader.test.ts index c76364976d..ff73718d50 100644 --- a/packages/backend-common/src/reading/GithubUrlReader.test.ts +++ b/packages/backend-common/src/reading/GithubUrlReader.test.ts @@ -20,7 +20,7 @@ import { GitHubIntegration, readGitHubIntegrationConfig, } from '@backstage/integration'; -import { msw } from '@backstage/test-utils'; +import { setupRequestMockHandlers } from '@backstage/test-utils'; import fs from 'fs-extra'; import mockFs from 'mock-fs'; import { rest } from 'msw'; @@ -73,7 +73,7 @@ const tmpDir = os.platform() === 'win32' ? 'C:\\tmp' : '/tmp'; describe('GithubUrlReader', () => { const worker = setupServer(); - msw.setupDefaultHandlers(worker); + setupRequestMockHandlers(worker); beforeEach(() => { mockFs({ diff --git a/packages/backend-common/src/reading/GitlabUrlReader.test.ts b/packages/backend-common/src/reading/GitlabUrlReader.test.ts index 331150bde3..c8a7e17ae3 100644 --- a/packages/backend-common/src/reading/GitlabUrlReader.test.ts +++ b/packages/backend-common/src/reading/GitlabUrlReader.test.ts @@ -15,7 +15,7 @@ */ import { ConfigReader } from '@backstage/config'; -import { msw } from '@backstage/test-utils'; +import { setupRequestMockHandlers } from '@backstage/test-utils'; import fs from 'fs-extra'; import mockFs from 'mock-fs'; import { rest } from 'msw'; @@ -77,7 +77,7 @@ describe('GitlabUrlReader', () => { }); const worker = setupServer(); - msw.setupDefaultHandlers(worker); + setupRequestMockHandlers(worker); describe('read', () => { beforeEach(() => { diff --git a/packages/backend-common/src/reading/index.ts b/packages/backend-common/src/reading/index.ts index 77096795ba..2c3394e4fc 100644 --- a/packages/backend-common/src/reading/index.ts +++ b/packages/backend-common/src/reading/index.ts @@ -20,6 +20,7 @@ export { GithubUrlReader } from './GithubUrlReader'; export { GitlabUrlReader } from './GitlabUrlReader'; export { AwsS3UrlReader } from './AwsS3UrlReader'; export type { + FromReadableArrayOptions, ReaderFactory, ReadTreeOptions, ReadTreeResponse, diff --git a/packages/backend-common/src/reading/types.ts b/packages/backend-common/src/reading/types.ts index ff799f548a..7e0904f18b 100644 --- a/packages/backend-common/src/reading/types.ts +++ b/packages/backend-common/src/reading/types.ts @@ -24,24 +24,41 @@ import { Config } from '@backstage/config'; * @public */ export type UrlReader = { - /* Used to read a single file and return its content. */ + /** + * Reads a single file and return its content. + */ read(url: string): Promise; /** - * A replacement for the read method that supports options and complex responses. + * Reads a single file and return its content. * - * Use this whenever it is available, as the read method will be deprecated and - * eventually removed in the future. + * @remarks + * + * This is a replacement for the read method that supports options and + * complex responses. + * + * Use this whenever it is available, as the read method will be + * deprecated and eventually removed in a future release. */ readUrl?(url: string, options?: ReadUrlOptions): Promise; - /* Used to read a file tree and download as a directory. */ + /** + * Reads a full or partial file tree. + */ readTree(url: string, options?: ReadTreeOptions): Promise; - /* Used to search a file in a tree using a glob pattern. */ + + /** + * Searches for a file in a tree using a glob pattern. + */ search(url: string, options?: SearchOptions): Promise; }; -/** @public */ +/** + * A predicate that decides whether a specific {@link UrlReader} can handle a + * given URL. + * + * @public + */ export type UrlReaderPredicateTuple = { predicate: (url: URL) => boolean; reader: UrlReader; @@ -49,7 +66,7 @@ export type UrlReaderPredicateTuple = { /** * A factory function that can read config to construct zero or more - * UrlReaders along with a predicate for when it should be used. + * {@link UrlReader}s along with a predicate for when it should be used. * * @public */ @@ -66,21 +83,28 @@ export type ReaderFactory = (options: { */ export type ReadUrlOptions = { /** - * An etag can be provided to check whether readUrl's response has changed from a previous execution. + * An ETag which can be provided to check whether a + * {@link UrlReader.readUrl} response has changed from a previous execution. * - * In the readUrl() response, an etag is returned along with the data. The etag is a unique identifer - * of the data, usually the commit SHA or etag from the target. + * @remarks * - * When an etag is given in ReadUrlOptions, readUrl will first compare the etag against the etag - * on the target. If they match, readUrl will throw a NotModifiedError indicating that the readUrl - * response will not differ from the previous response which included this particular etag. If they - * do not match, readUrl will return the rest of ReadUrlResponse along with a new etag. + * In the {@link UrlReader.readUrl} response, an ETag is returned along with + * the data. The ETag is a unique identifier of the data, usually the commit + * SHA or ETag from the target. + * + * When an ETag is given in ReadUrlOptions, {@link UrlReader.readUrl} will + * first compare the ETag against the ETag of the target. If they match, + * {@link UrlReader.readUrl} will throw a + * {@link @backstage/errors#NotModifiedError} indicating that the response + * will not differ from the previous response which included this particular + * ETag. If they do not match, {@link UrlReader.readUrl} will return the rest + * of the response along with a new ETag. */ etag?: string; }; /** - * A response object for readUrl operations. + * A response object for {@link UrlReader.readUrl} operations. * * @public */ @@ -92,13 +116,16 @@ export type ReadUrlResponse = { /** * Etag returned by content provider. + * + * @remarks + * * Can be used to compare and cache responses when doing subsequent calls. */ etag?: string; }; /** - * An options object for readTree operations. + * An options object for {@link UrlReader.readTree} operations. * * @public */ @@ -106,6 +133,8 @@ export type ReadTreeOptions = { /** * A filter that can be used to select which files should be included. * + * @remarks + * * The path passed to the filter function is the relative path from the URL * that the file tree is fetched from, without any leading '/'. * @@ -113,56 +142,82 @@ export type ReadTreeOptions = { * at https://github.com/my/repo/blob/master/my-dir/my-subdir/my-file.txt will * be represented as my-subdir/my-file.txt * - * If no filter is provided all files are extracted. + * If no filter is provided, all files are extracted. */ filter?(path: string, info?: { size: number }): boolean; /** - * An etag can be provided to check whether readTree's response has changed from a previous execution. + * An ETag which can be provided to check whether a + * {@link UrlReader.readTree} response has changed from a previous execution. * - * In the readTree() response, an etag is returned along with the tree blob. The etag is a unique identifer - * of the tree blob, usually the commit SHA or etag from the target. + * @remarks * - * When an etag is given in ReadTreeOptions, readTree will first compare the etag against the etag - * on the target branch. If they match, readTree will throw a NotModifiedError indicating that the readTree - * response will not differ from the previous response which included this particular etag. If they - * do not match, readTree will return the rest of ReadTreeResponse along with a new etag. + * In the {@link UrlReader.readTree} response, an ETag is returned along with + * the tree blob. The ETag is a unique identifier of the tree blob, usually + * the commit SHA or ETag from the target. + * + * When an ETag is given as a request option, {@link UrlReader.readTree} will + * first compare the ETag against the ETag on the target branch. If they + * match, {@link UrlReader.readTree} will throw a + * {@link @backstage/errors#NotModifiedError} indicating that the response + * will not differ from the previous response which included this particular + * ETag. If they do not match, {@link UrlReader.readTree} will return the + * rest of the response along with a new ETag. */ etag?: string; }; -/** @public */ +/** + * Options that control {@link ReadTreeResponse.dir} execution. + * + * @public + */ export type ReadTreeResponseDirOptions = { - /** The directory to write files to. Defaults to the OS tmpdir or `backend.workingDirectory` if set in config */ + /** + * The directory to write files to. + * + * @remarks + * + * Defaults to the OS tmpdir, or `backend.workingDirectory` if set in config. + */ targetDir?: string; }; /** - * A response object for readTree operations. + * A response object for {@link UrlReader.readTree} operations. * * @public */ export type ReadTreeResponse = { /** - * files() returns an array of all the files inside the tree and corresponding functions to read their content. + * Returns an array of all the files inside the tree, and corresponding + * functions to read their content. */ files(): Promise; + + /** + * Returns the tree contents as a binary archive, using a stream. + */ archive(): Promise; /** - * dir() extracts the tree response into a directory and returns the path of the directory. + * Extracts the tree response into a directory and returns the path of the + * directory. */ dir(options?: ReadTreeResponseDirOptions): Promise; /** * Etag returned by content provider. + * + * @remarks + * * Can be used to compare and cache responses when doing subsequent calls. */ etag: string; }; /** - * Represents a single file in a readTree response. + * Represents a single file in a {@link UrlReader.readTree} response. * * @public */ @@ -171,7 +226,11 @@ export type ReadTreeResponseFile = { content(): Promise; }; -/** @public */ +/** + * Options that control execution of {@link ReadTreeResponseFactory} methods. + * + * @public + */ export type ReadTreeResponseFactoryOptions = { // A binary stream of a tar archive. stream: Readable; @@ -183,11 +242,21 @@ export type ReadTreeResponseFactoryOptions = { // Filter passed on from the ReadTreeOptions filter?: (path: string, info?: { size: number }) => boolean; }; -/** @public */ + +/** + * Options that control {@link ReadTreeResponseFactory.fromReadableArray} + * execution. + * + * @public + */ export type FromReadableArrayOptions = Array<{ - // Data in the form of a readable + /** + * The raw data itself. + */ data: Readable; - // A string containing the filepath of the data + /** + * The filepath of the data. + */ path: string; }>; @@ -213,7 +282,7 @@ export type SearchOptions = { /** * An etag can be provided to check whether the search response has changed from a previous execution. * - * In the search() response, an etag is returned along with the files. The etag is a unique identifer + * In the search() response, an etag is returned along with the files. The etag is a unique identifier * of the current tree, usually the commit SHA or etag from the target. * * When an etag is given in SearchOptions, search will first compare the etag against the etag @@ -236,7 +305,7 @@ export type SearchResponse = { files: SearchResponseFile[]; /** - * A unique identifer of the current remote tree, usually the commit SHA or etag from the target. + * A unique identifier of the current remote tree, usually the commit SHA or etag from the target. */ etag: string; }; diff --git a/packages/backend-common/src/util/escapeRegExp.test.ts b/packages/backend-common/src/util/escapeRegExp.test.ts new file mode 100644 index 0000000000..13c6ae4a5a --- /dev/null +++ b/packages/backend-common/src/util/escapeRegExp.test.ts @@ -0,0 +1,84 @@ +/* + * Copyright 2021 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 { escapeRegExp } from './escapeRegExp'; + +describe('escapeRegExp', () => { + test('does not escape non-regex characters', () => { + expect(escapeRegExp('Backstage Backstage')).toBe('Backstage Backstage'); + }); + + test('all the characters', () => { + expect(escapeRegExp('^$\\.*+?()[]{}|')).toBe( + '\\^\\$\\\\\\.\\*\\+\\?\\(\\)\\[\\]\\{\\}\\|', + ); + }); + + test('character: ^', () => { + expect(escapeRegExp('^')).toBe('\\^'); + }); + + test('character: $', () => { + expect(escapeRegExp('$')).toBe('\\$'); + }); + + test('character: \\', () => { + expect(escapeRegExp('\\')).toBe('\\\\'); + }); + + test('character: .', () => { + expect(escapeRegExp('.')).toBe('\\.'); + }); + + test('character: *', () => { + expect(escapeRegExp('*')).toBe('\\*'); + }); + + test('character: +', () => { + expect(escapeRegExp('+')).toBe('\\+'); + }); + + test('character: ?', () => { + expect(escapeRegExp('?')).toBe('\\?'); + }); + + test('character: (', () => { + expect(escapeRegExp('(')).toBe('\\('); + }); + + test('character: )', () => { + expect(escapeRegExp(')')).toBe('\\)'); + }); + + test('character: [', () => { + expect(escapeRegExp('[')).toBe('\\['); + }); + + test('character: ]', () => { + expect(escapeRegExp(']')).toBe('\\]'); + }); + + test('character: {', () => { + expect(escapeRegExp('{')).toBe('\\{'); + }); + + test('character: }', () => { + expect(escapeRegExp('}')).toBe('\\}'); + }); + + test('character: |', () => { + expect(escapeRegExp('|')).toBe('\\|'); + }); +}); diff --git a/packages/backend-common/src/util/escapeRegExp.ts b/packages/backend-common/src/util/escapeRegExp.ts new file mode 100644 index 0000000000..bc78967ebe --- /dev/null +++ b/packages/backend-common/src/util/escapeRegExp.ts @@ -0,0 +1,24 @@ +/* + * Copyright 2021 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. + */ + +/** + * Escapes a given string to be used inside a RegExp. + * + * Taken from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions + */ +export const escapeRegExp = (text: string) => { + return text.replace(/[.*+?^${}(\)|[\]\\]/g, '\\$&'); +}; diff --git a/packages/catalog-client/package.json b/packages/catalog-client/package.json index f8dfd59e41..d4ba2c20f6 100644 --- a/packages/catalog-client/package.json +++ b/packages/catalog-client/package.json @@ -37,7 +37,7 @@ "devDependencies": { "@backstage/cli": "^0.8.0", "@types/jest": "^26.0.7", - "msw": "^0.29.0" + "msw": "^0.35.0" }, "files": [ "dist" diff --git a/packages/catalog-model/CHANGELOG.md b/packages/catalog-model/CHANGELOG.md index 066b01cd50..e0c067c9c7 100644 --- a/packages/catalog-model/CHANGELOG.md +++ b/packages/catalog-model/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/catalog-model +## 0.9.6 + +### Patch Changes + +- 10615525f3: Switch to use the json and observable types from `@backstage/types` +- Updated dependencies + - @backstage/config@0.1.11 + - @backstage/errors@0.1.4 + ## 0.9.5 ### Patch Changes diff --git a/packages/catalog-model/package.json b/packages/catalog-model/package.json index 615e80b684..b64e536578 100644 --- a/packages/catalog-model/package.json +++ b/packages/catalog-model/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/catalog-model", "description": "Types and validators that help describe the model of a Backstage Catalog", - "version": "0.9.5", + "version": "0.9.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,8 +30,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/config": "^0.1.10", - "@backstage/errors": "^0.1.3", + "@backstage/config": "^0.1.11", + "@backstage/errors": "^0.1.4", "@backstage/types": "^0.1.1", "@types/json-schema": "^7.0.5", "@types/yup": "^0.29.13", @@ -42,7 +42,7 @@ "yup": "^0.32.9" }, "devDependencies": { - "@backstage/cli": "^0.8.0", + "@backstage/cli": "^0.8.1", "@types/jest": "^26.0.7", "@types/lodash": "^4.14.151", "yaml": "^1.9.2" diff --git a/packages/cli-common/CHANGELOG.md b/packages/cli-common/CHANGELOG.md index b4b87fa103..f3978798c6 100644 --- a/packages/cli-common/CHANGELOG.md +++ b/packages/cli-common/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/cli-common +## 0.1.5 + +### Patch Changes + +- c2d50a0073: Add docs to the last export of cli-common + ## 0.1.4 ### Patch Changes diff --git a/packages/cli-common/api-report.md b/packages/cli-common/api-report.md index 371671e63a..4b61cfedb8 100644 --- a/packages/cli-common/api-report.md +++ b/packages/cli-common/api-report.md @@ -21,6 +21,6 @@ export type Paths = { resolveTargetRoot: ResolveFunc; }; -// @public (undocumented) +// @public export type ResolveFunc = (...paths: string[]) => string; ``` diff --git a/packages/cli-common/package.json b/packages/cli-common/package.json index 0693b555a6..5916cdb017 100644 --- a/packages/cli-common/package.json +++ b/packages/cli-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/cli-common", "description": "Common functionality used by cli, backend, and create-app", - "version": "0.1.4", + "version": "0.1.5", "private": false, "main": "src/index.ts", "types": "src/index.ts", diff --git a/packages/cli-common/src/paths.ts b/packages/cli-common/src/paths.ts index 4aa9d4b76e..c9f486752f 100644 --- a/packages/cli-common/src/paths.ts +++ b/packages/cli-common/src/paths.ts @@ -17,7 +17,12 @@ import fs from 'fs'; import { dirname, resolve as resolvePath } from 'path'; -/** @public */ +/** + * A function that takes a set of path fragments and resolves them into a + * single complete path, relative to some root. + * + * @public + */ export type ResolveFunc = (...paths: string[]) => string; /** diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 7cb3c5be91..48f38cbc8a 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/cli +## 0.8.1 + +### Patch Changes + +- f1e96dc5b1: Update usage of msw in default plugin template +- b0dc1fd241: bump `@spotify/eslint-config-base` from 9.0.2 to 12.0.0 +- c5bb1df55d: Bump `msw` to `v0.35.0` to resolve [CVE-2021-32796](https://github.com/advisories/GHSA-5fg8-2547-mr8q). +- 10615525f3: Switch to use the json and observable types from `@backstage/types` +- Updated dependencies + - @backstage/config@0.1.11 + - @backstage/cli-common@0.1.5 + - @backstage/errors@0.1.4 + - @backstage/config-loader@0.7.1 + ## 0.8.0 ### Minor Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index 62a008087e..c023313fe7 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/cli", "description": "CLI for developing Backstage plugins and apps", - "version": "0.8.0", + "version": "0.8.1", "private": false, "publishConfig": { "access": "public" @@ -28,10 +28,10 @@ "backstage-cli": "bin/backstage-cli" }, "dependencies": { - "@backstage/cli-common": "^0.1.4", - "@backstage/config": "^0.1.10", - "@backstage/config-loader": "^0.7.0", - "@backstage/errors": "^0.1.3", + "@backstage/cli-common": "^0.1.5", + "@backstage/config": "^0.1.11", + "@backstage/config-loader": "^0.7.1", + "@backstage/errors": "^0.1.4", "@backstage/types": "^0.1.1", "@hot-loader/react-dom": "^16.13.0", "@lerna/package-graph": "^4.0.0", @@ -41,7 +41,7 @@ "@rollup/plugin-json": "^4.0.2", "@rollup/plugin-node-resolve": "^13.0.0", "@rollup/plugin-yaml": "^3.0.0", - "@spotify/eslint-config-base": "^9.0.0", + "@spotify/eslint-config-base": "^12.0.0", "@spotify/eslint-config-react": "^10.0.0", "@spotify/eslint-config-typescript": "^10.0.0", "@sucrase/jest-plugin": "^2.1.1", @@ -110,21 +110,21 @@ "typescript": "^4.0.3", "util": "^0.12.3", "webpack": "^5.48.0", - "webpack-dev-server": "4.0.0-rc.0", + "webpack-dev-server": "4.3.1", "webpack-node-externals": "^3.0.0", "yaml": "^1.10.0", "yml-loader": "^2.1.0", "yn": "^4.0.0" }, "devDependencies": { - "@backstage/backend-common": "^0.9.7", - "@backstage/config": "^0.1.10", - "@backstage/core-components": "^0.7.1", - "@backstage/core-plugin-api": "^0.1.11", - "@backstage/core-app-api": "^0.1.18", + "@backstage/backend-common": "^0.9.8", + "@backstage/config": "^0.1.11", + "@backstage/core-components": "^0.7.2", + "@backstage/core-plugin-api": "^0.1.12", + "@backstage/core-app-api": "^0.1.19", "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.19", - "@backstage/theme": "^0.2.11", + "@backstage/test-utils": "^0.1.20", + "@backstage/theme": "^0.2.12", "@types/diff": "^5.0.0", "@types/express": "^4.17.6", "@types/fs-extra": "^9.0.1", diff --git a/packages/cli/templates/default-backend-plugin/package.json.hbs b/packages/cli/templates/default-backend-plugin/package.json.hbs index 43b9e83fe1..5cca7dcb07 100644 --- a/packages/cli/templates/default-backend-plugin/package.json.hbs +++ b/packages/cli/templates/default-backend-plugin/package.json.hbs @@ -36,7 +36,7 @@ "@backstage/cli": "{{versionQuery '@backstage/cli'}}", "@types/supertest": "{{versionQuery '@types/supertest' '2.0.8'}}", "supertest": "{{versionQuery 'supertest' '4.0.2'}}", - "msw": "{{versionQuery 'msw' '0.29.0'}}" + "msw": "{{versionQuery 'msw' '0.35.0'}}" }, "files": [ "dist" diff --git a/packages/cli/templates/default-plugin/package.json.hbs b/packages/cli/templates/default-plugin/package.json.hbs index ef56d55343..41376821ba 100644 --- a/packages/cli/templates/default-plugin/package.json.hbs +++ b/packages/cli/templates/default-plugin/package.json.hbs @@ -44,7 +44,7 @@ "@testing-library/user-event": "{{versionQuery '@testing-library/user-event' '13.1.8'}}", "@types/jest": "{{versionQuery '@types/jest' '26.0.7'}}", "@types/node": "{{versionQuery '@types/node' '14.14.32'}}", - "msw": "{{versionQuery 'msw' '0.29.0'}}", + "msw": "{{versionQuery 'msw' '0.35.0'}}", "cross-fetch": "{{versionQuery 'cross-fetch' '3.0.6'}}" }, "files": [ diff --git a/packages/cli/templates/default-plugin/src/components/ExampleComponent/ExampleComponent.test.tsx.hbs b/packages/cli/templates/default-plugin/src/components/ExampleComponent/ExampleComponent.test.tsx.hbs index 0044b67a37..ccbebcac40 100644 --- a/packages/cli/templates/default-plugin/src/components/ExampleComponent/ExampleComponent.test.tsx.hbs +++ b/packages/cli/templates/default-plugin/src/components/ExampleComponent/ExampleComponent.test.tsx.hbs @@ -4,12 +4,15 @@ import { ThemeProvider } from '@material-ui/core'; import { lightTheme } from '@backstage/theme'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; -import { msw, renderInTestApp } from '@backstage/test-utils'; +import { + setupRequestMockHandlers, + renderInTestApp, +} from "@backstage/test-utils"; describe('ExampleComponent', () => { const server = setupServer(); // Enable sane handlers for network requests - msw.setupDefaultHandlers(server); + setupRequestMockHandlers(server); // setup mock response beforeEach(() => { diff --git a/packages/cli/templates/default-plugin/src/components/ExampleFetchComponent/ExampleFetchComponent.test.tsx.hbs b/packages/cli/templates/default-plugin/src/components/ExampleFetchComponent/ExampleFetchComponent.test.tsx.hbs index fa1e289d8e..95533c899d 100644 --- a/packages/cli/templates/default-plugin/src/components/ExampleFetchComponent/ExampleFetchComponent.test.tsx.hbs +++ b/packages/cli/templates/default-plugin/src/components/ExampleFetchComponent/ExampleFetchComponent.test.tsx.hbs @@ -3,12 +3,12 @@ import { render } from '@testing-library/react'; import { ExampleFetchComponent } from './ExampleFetchComponent'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; -import { msw } from '@backstage/test-utils'; +import { setupRequestMockHandlers } from '@backstage/test-utils'; describe('ExampleFetchComponent', () => { const server = setupServer(); // Enable sane handlers for network requests - msw.setupDefaultHandlers(server); + setupRequestMockHandlers(server); // setup mock response beforeEach(() => { diff --git a/packages/codemods/CHANGELOG.md b/packages/codemods/CHANGELOG.md index 7aabaef583..fbb2076167 100644 --- a/packages/codemods/CHANGELOG.md +++ b/packages/codemods/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/codemods +## 0.1.20 + +### Patch Changes + +- Updated dependencies + - @backstage/cli-common@0.1.5 + - @backstage/core-components@0.7.2 + - @backstage/core-app-api@0.1.19 + - @backstage/core-plugin-api@0.1.12 + ## 0.1.19 ### Patch Changes diff --git a/packages/codemods/package.json b/packages/codemods/package.json index 77bdd181be..0dc0e9a0d5 100644 --- a/packages/codemods/package.json +++ b/packages/codemods/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/codemods", "description": "A collection of codemods for Backstage projects", - "version": "0.1.19", + "version": "0.1.20", "private": false, "publishConfig": { "access": "public", @@ -31,7 +31,7 @@ "backstage-codemods": "bin/backstage-codemods" }, "dependencies": { - "@backstage/cli-common": "0.1.4", + "@backstage/cli-common": "0.1.5", "@backstage/core-app-api": "*", "@backstage/core-components": "*", "@backstage/core-plugin-api": "*", diff --git a/packages/config-loader/CHANGELOG.md b/packages/config-loader/CHANGELOG.md index 0b4ef9a5f3..dcaec00816 100644 --- a/packages/config-loader/CHANGELOG.md +++ b/packages/config-loader/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/config-loader +## 0.7.1 + +### Patch Changes + +- 10615525f3: Switch to use the json and observable types from `@backstage/types` +- ea21f7f567: bump `typescript-json-schema` from 0.50.1 to 0.51.0 +- Updated dependencies + - @backstage/config@0.1.11 + - @backstage/cli-common@0.1.5 + - @backstage/errors@0.1.4 + ## 0.7.0 ### Minor Changes diff --git a/packages/config-loader/package.json b/packages/config-loader/package.json index efcf753295..910dd87108 100644 --- a/packages/config-loader/package.json +++ b/packages/config-loader/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/config-loader", "description": "Config loading functionality used by Backstage backend, and CLI", - "version": "0.7.0", + "version": "0.7.1", "private": false, "publishConfig": { "access": "public", @@ -30,9 +30,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/cli-common": "^0.1.4", - "@backstage/config": "^0.1.9", - "@backstage/errors": "^0.1.3", + "@backstage/cli-common": "^0.1.5", + "@backstage/config": "^0.1.11", + "@backstage/errors": "^0.1.4", "@backstage/types": "^0.1.1", "@types/json-schema": "^7.0.6", "ajv": "^7.0.3", @@ -41,7 +41,7 @@ "json-schema": "^0.3.0", "json-schema-merge-allof": "^0.8.1", "json-schema-traverse": "^1.0.0", - "typescript-json-schema": "^0.50.1", + "typescript-json-schema": "^0.51.0", "yaml": "^1.9.2", "yup": "^0.32.9", "node-fetch": "2.6.5" diff --git a/packages/config/CHANGELOG.md b/packages/config/CHANGELOG.md index 9735c330c1..de62de5466 100644 --- a/packages/config/CHANGELOG.md +++ b/packages/config/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/config +## 0.1.11 + +### Patch Changes + +- 10d267a1b7: Minor exports cleanup +- 41c49884d2: Start using the new `@backstage/types` package. Initially, this means using the `Observable` and `Json*` types from there. The types also remain in their old places but deprecated, and will be removed in a future release. +- 925a967f36: Replace usage of test-utils-core with test-utils + ## 0.1.10 ### Patch Changes diff --git a/packages/config/api-report.md b/packages/config/api-report.md index 205db6ef2b..efa6b85559 100644 --- a/packages/config/api-report.md +++ b/packages/config/api-report.md @@ -46,39 +46,22 @@ export class ConfigReader implements Config { fallback?: ConfigReader | undefined, prefix?: string, ); - // (undocumented) static fromConfigs(configs: AppConfig[]): ConfigReader; - // (undocumented) get(key?: string): T; - // (undocumented) getBoolean(key: string): boolean; - // (undocumented) getConfig(key: string): ConfigReader; - // (undocumented) getConfigArray(key: string): ConfigReader[]; - // (undocumented) getNumber(key: string): number; - // (undocumented) getOptional(key?: string): T | undefined; - // (undocumented) getOptionalBoolean(key: string): boolean | undefined; - // (undocumented) getOptionalConfig(key: string): ConfigReader | undefined; - // (undocumented) getOptionalConfigArray(key: string): ConfigReader[] | undefined; - // (undocumented) getOptionalNumber(key: string): number | undefined; - // (undocumented) getOptionalString(key: string): string | undefined; - // (undocumented) getOptionalStringArray(key: string): string[] | undefined; - // (undocumented) getString(key: string): string; - // (undocumented) getStringArray(key: string): string[]; - // (undocumented) has(key: string): boolean; - // (undocumented) keys(): string[]; } diff --git a/packages/config/package.json b/packages/config/package.json index 719ab22772..d162b73cae 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/config", "description": "Config API used by Backstage core, backend, and CLI", - "version": "0.1.10", + "version": "0.1.11", "private": false, "publishConfig": { "access": "public", @@ -34,7 +34,7 @@ "lodash": "^4.17.21" }, "devDependencies": { - "@backstage/test-utils": "^0.1.19", + "@backstage/test-utils": "^0.1.20", "@types/jest": "^26.0.7", "@types/node": "^14.14.32" }, diff --git a/packages/config/src/reader.ts b/packages/config/src/reader.ts index bc8a860c85..8c0c4140a5 100644 --- a/packages/config/src/reader.ts +++ b/packages/config/src/reader.ts @@ -72,6 +72,9 @@ export class ConfigReader implements Config { private filteredKeys?: string[]; private notifiedFilteredKeys = new Set(); + /** + * Instantiates the config reader from a list of application config objects. + */ static fromConfigs(configs: AppConfig[]): ConfigReader { if (configs.length === 0) { return new ConfigReader(undefined); @@ -96,6 +99,7 @@ export class ConfigReader implements Config { private readonly prefix: string = '', ) {} + /** {@inheritdoc Config.has} */ has(key: string): boolean { const value = this.readValue(key); if (value !== undefined) { @@ -104,12 +108,14 @@ export class ConfigReader implements Config { return this.fallback?.has(key) ?? false; } + /** {@inheritdoc Config.keys} */ keys(): string[] { const localKeys = this.data ? Object.keys(this.data) : []; const fallbackKeys = this.fallback?.keys() ?? []; return [...new Set([...localKeys, ...fallbackKeys])]; } + /** {@inheritdoc Config.get} */ get(key?: string): T { const value = this.getOptional(key); if (value === undefined) { @@ -118,6 +124,7 @@ export class ConfigReader implements Config { return value as T; } + /** {@inheritdoc Config.getOptional} */ getOptional(key?: string): T | undefined { const value = this.readValue(key); const fallbackValue = this.fallback?.getOptional(key); @@ -154,6 +161,7 @@ export class ConfigReader implements Config { ).value as T; } + /** {@inheritdoc Config.getConfig} */ getConfig(key: string): ConfigReader { const value = this.getOptionalConfig(key); if (value === undefined) { @@ -162,6 +170,7 @@ export class ConfigReader implements Config { return value; } + /** {@inheritdoc Config.getOptionalConfig} */ getOptionalConfig(key: string): ConfigReader | undefined { const value = this.readValue(key); const fallbackConfig = this.fallback?.getOptionalConfig(key); @@ -177,6 +186,7 @@ export class ConfigReader implements Config { return fallbackConfig; } + /** {@inheritdoc Config.getConfigArray} */ getConfigArray(key: string): ConfigReader[] { const value = this.getOptionalConfigArray(key); if (value === undefined) { @@ -185,6 +195,7 @@ export class ConfigReader implements Config { return value; } + /** {@inheritdoc Config.getOptionalConfigArray} */ getOptionalConfigArray(key: string): ConfigReader[] | undefined { const configs = this.readConfigValue(key, values => { if (!Array.isArray(values)) { @@ -220,6 +231,7 @@ export class ConfigReader implements Config { return configs.map((obj, index) => this.copy(obj, `${key}[${index}]`)); } + /** {@inheritdoc Config.getNumber} */ getNumber(key: string): number { const value = this.getOptionalNumber(key); if (value === undefined) { @@ -228,6 +240,7 @@ export class ConfigReader implements Config { return value; } + /** {@inheritdoc Config.getOptionalNumber} */ getOptionalNumber(key: string): number | undefined { const value = this.readConfigValue( key, @@ -247,6 +260,7 @@ export class ConfigReader implements Config { return number; } + /** {@inheritdoc Config.getBoolean} */ getBoolean(key: string): boolean { const value = this.getOptionalBoolean(key); if (value === undefined) { @@ -255,6 +269,7 @@ export class ConfigReader implements Config { return value; } + /** {@inheritdoc Config.getOptionalBoolean} */ getOptionalBoolean(key: string): boolean | undefined { return this.readConfigValue( key, @@ -262,6 +277,7 @@ export class ConfigReader implements Config { ); } + /** {@inheritdoc Config.getString} */ getString(key: string): string { const value = this.getOptionalString(key); if (value === undefined) { @@ -270,6 +286,7 @@ export class ConfigReader implements Config { return value; } + /** {@inheritdoc Config.getOptionalString} */ getOptionalString(key: string): string | undefined { return this.readConfigValue( key, @@ -278,6 +295,7 @@ export class ConfigReader implements Config { ); } + /** {@inheritdoc Config.getStringArray} */ getStringArray(key: string): string[] { const value = this.getOptionalStringArray(key); if (value === undefined) { @@ -286,6 +304,7 @@ export class ConfigReader implements Config { return value; } + /** {@inheritdoc Config.getOptionalStringArray} */ getOptionalStringArray(key: string): string[] | undefined { return this.readConfigValue(key, values => { if (!Array.isArray(values)) { diff --git a/packages/core-app-api/CHANGELOG.md b/packages/core-app-api/CHANGELOG.md index e01e89f04c..ff75f5bf81 100644 --- a/packages/core-app-api/CHANGELOG.md +++ b/packages/core-app-api/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/core-app-api +## 0.1.19 + +### Patch Changes + +- 10615525f3: Switch to use the json and observable types from `@backstage/types` +- 41c49884d2: Start using the new `@backstage/types` package. Initially, this means using the `Observable` and `Json*` types from there. The types also remain in their old places but deprecated, and will be removed in a future release. +- 925a967f36: Replace usage of test-utils-core with test-utils +- 6b615e92c8: Api cleanup, adding `@public` where necessary and tweaking some comments +- Updated dependencies + - @backstage/config@0.1.11 + - @backstage/theme@0.2.12 + - @backstage/core-components@0.7.2 + - @backstage/core-plugin-api@0.1.12 + ## 0.1.18 ### Patch Changes diff --git a/packages/core-app-api/api-report.md b/packages/core-app-api/api-report.md index 03c29daa01..09d3313c84 100644 --- a/packages/core-app-api/api-report.md +++ b/packages/core-app-api/api-report.md @@ -58,8 +58,6 @@ import { StorageApi } from '@backstage/core-plugin-api'; import { StorageValueChange } from '@backstage/core-plugin-api'; import { SubRouteRef } from '@backstage/core-plugin-api'; -// Warning: (ae-missing-release-tag) "AlertApiForwarder" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export class AlertApiForwarder implements AlertApi { // (undocumented) @@ -68,8 +66,6 @@ export class AlertApiForwarder implements AlertApi { post(alert: AlertMessage): void; } -// Warning: (ae-missing-release-tag) "ApiFactoryHolder" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type ApiFactoryHolder = { get(api: ApiRef): @@ -83,8 +79,6 @@ export type ApiFactoryHolder = { | undefined; }; -// Warning: (ae-missing-release-tag) "ApiFactoryRegistry" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export class ApiFactoryRegistry implements ApiFactoryHolder { // (undocumented) @@ -109,11 +103,9 @@ export class ApiFactoryRegistry implements ApiFactoryHolder { >(scope: ApiFactoryScope, factory: ApiFactory): boolean; } -// Warning: (ae-missing-release-tag) "ApiProvider" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export const ApiProvider: { - ({ apis, children }: PropsWithChildren): JSX.Element; + (props: PropsWithChildren): JSX.Element; propTypes: { apis: PropTypes.Validator< PropTypes.InferProps<{ @@ -124,9 +116,7 @@ export const ApiProvider: { }; }; -// Warning: (ae-missing-release-tag) "ApiRegistry" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export class ApiRegistry implements ApiHolder { constructor(apis: Map); // Warning: (ae-forgotten-export) The symbol "ApiRegistryBuilder" needs to be exported by the entry point index.d.ts @@ -134,22 +124,14 @@ export class ApiRegistry implements ApiHolder { // (undocumented) static builder(): ApiRegistryBuilder; // Warning: (ae-forgotten-export) The symbol "ApiImpl" needs to be exported by the entry point index.d.ts - // - // (undocumented) static from(apis: ApiImpl[]): ApiRegistry; // (undocumented) get(api: ApiRef): T | undefined; - // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen - // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen static with(api: ApiRef, impl: T): ApiRegistry; - // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen - // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen with(api: ApiRef, impl: T): ApiRegistry; } -// Warning: (ae-missing-release-tag) "ApiResolver" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export class ApiResolver implements ApiHolder { constructor(factories: ApiFactoryHolder); // (undocumented) @@ -160,9 +142,7 @@ export class ApiResolver implements ApiHolder { ): void; } -// Warning: (ae-missing-release-tag) "AppComponents" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export type AppComponents = { NotFoundErrorPage: ComponentType<{}>; BootErrorPage: ComponentType; @@ -173,23 +153,17 @@ export type AppComponents = { SignInPage?: ComponentType; }; -// Warning: (ae-missing-release-tag) "AppConfigLoader" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type AppConfigLoader = () => Promise; -// Warning: (ae-missing-release-tag) "AppContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export type AppContext = { getPlugins(): BackstagePlugin[]; getSystemIcon(key: string): IconComponent | undefined; getComponents(): AppComponents; }; -// Warning: (ae-missing-release-tag) "AppOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export type AppOptions = { apis?: Iterable; icons?: Partial & { @@ -205,9 +179,8 @@ export type AppOptions = { // Warning: (ae-forgotten-export) The symbol "PartialKeys" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "TargetRouteMap" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "KeysWithType" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "AppRouteBinder" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // -// @public (undocumented) +// @public export type AppRouteBinder = < ExternalRoutes extends { [name: string]: ExternalRouteRef; @@ -220,9 +193,7 @@ export type AppRouteBinder = < >, ) => void; -// Warning: (ae-missing-release-tag) "AppThemeSelector" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export class AppThemeSelector implements AppThemeApi { constructor(themes: AppTheme[]); // (undocumented) @@ -237,9 +208,7 @@ export class AppThemeSelector implements AppThemeApi { setActiveThemeId(themeId?: string): void; } -// Warning: (ae-missing-release-tag) "AtlassianAuth" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export class AtlassianAuth { // Warning: (ae-forgotten-export) The symbol "OAuthApiCreateOptions" needs to be exported by the entry point index.d.ts // @@ -252,9 +221,7 @@ export class AtlassianAuth { }: OAuthApiCreateOptions): typeof atlassianAuthApiRef.T; } -// Warning: (ae-missing-release-tag) "Auth0Auth" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export class Auth0Auth { // (undocumented) static create({ @@ -266,9 +233,7 @@ export class Auth0Auth { }: OAuthApiCreateOptions): typeof auth0AuthApiRef.T; } -// Warning: (ae-missing-release-tag) "BackstageApp" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export type BackstageApp = { getPlugins(): BackstagePlugin[]; getSystemIcon(key: string): IconComponent | undefined; @@ -276,19 +241,20 @@ export type BackstageApp = { getRouter(): ComponentType<{}>; }; -// Warning: (ae-missing-release-tag) "BackstagePluginWithAnyOutput" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export type BackstagePluginWithAnyOutput = Omit< BackstagePlugin, 'output' > & { - output(): (PluginOutput | UnknownPluginOutput)[]; + output(): ( + | PluginOutput + | { + type: string; + } + )[]; }; -// Warning: (ae-missing-release-tag) "BitbucketAuth" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export class BitbucketAuth { // (undocumented) static create({ @@ -300,9 +266,7 @@ export class BitbucketAuth { }: OAuthApiCreateOptions): typeof bitbucketAuthApiRef.T; } -// Warning: (ae-missing-release-tag) "BitbucketSession" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export type BitbucketSession = { providerInfo: { accessToken: string; @@ -313,9 +277,7 @@ export type BitbucketSession = { backstageIdentity: BackstageIdentity; }; -// Warning: (ae-missing-release-tag) "BootErrorPageProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export type BootErrorPageProps = { step: 'load-config' | 'load-chunk'; error: Error; @@ -324,18 +286,13 @@ export type BootErrorPageProps = { export { ConfigReader }; // Warning: (ae-forgotten-export) The symbol "PrivateAppImpl" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "createApp" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public export function createApp(options?: AppOptions): PrivateAppImpl; -// Warning: (ae-missing-release-tag) "defaultConfigLoader" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export const defaultConfigLoader: AppConfigLoader; -// Warning: (ae-missing-release-tag) "ErrorAlerter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export class ErrorAlerter implements ErrorApi { constructor(alertApi: AlertApi, errorApi: ErrorApi); @@ -352,8 +309,6 @@ export class ErrorAlerter implements ErrorApi { post(error: Error, context?: ErrorContext): void; } -// Warning: (ae-missing-release-tag) "ErrorApiForwarder" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export class ErrorApiForwarder implements ErrorApi { // (undocumented) @@ -365,23 +320,17 @@ export class ErrorApiForwarder implements ErrorApi { post(error: Error, context?: ErrorContext): void; } -// Warning: (ae-missing-release-tag) "ErrorBoundaryFallbackProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export type ErrorBoundaryFallbackProps = { plugin?: BackstagePlugin; error: Error; resetError: () => void; }; -// Warning: (ae-missing-release-tag) "FeatureFlagged" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export const FeatureFlagged: (props: FeatureFlaggedProps) => JSX.Element; -// Warning: (ae-missing-release-tag) "FeatureFlaggedProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export type FeatureFlaggedProps = { children: ReactNode; } & ( @@ -393,15 +342,15 @@ export type FeatureFlaggedProps = { } ); -// Warning: (ae-forgotten-export) The symbol "FlatRoutesProps" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "FlatRoutes" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export const FlatRoutes: (props: FlatRoutesProps) => JSX.Element | null; -// Warning: (ae-missing-release-tag) "GithubAuth" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public +export type FlatRoutesProps = { + children: ReactNode; +}; + +// @public export class GithubAuth implements OAuthApi, SessionApi { // Warning: (ae-forgotten-export) The symbol "SessionManager" needs to be exported by the entry point index.d.ts constructor(sessionManager: SessionManager); @@ -431,9 +380,7 @@ export class GithubAuth implements OAuthApi, SessionApi { signOut(): Promise; } -// Warning: (ae-missing-release-tag) "GithubSession" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export type GithubSession = { providerInfo: { accessToken: string; @@ -444,9 +391,7 @@ export type GithubSession = { backstageIdentity: BackstageIdentity; }; -// Warning: (ae-missing-release-tag) "GitlabAuth" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export class GitlabAuth { // (undocumented) static create({ @@ -458,9 +403,7 @@ export class GitlabAuth { }: OAuthApiCreateOptions): typeof gitlabAuthApiRef.T; } -// Warning: (ae-missing-release-tag) "GoogleAuth" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export class GoogleAuth { // (undocumented) static create({ @@ -472,8 +415,6 @@ export class GoogleAuth { }: OAuthApiCreateOptions): typeof googleAuthApiRef.T; } -// Warning: (ae-missing-release-tag) "LocalStorageFeatureFlags" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export class LocalStorageFeatureFlags implements FeatureFlagsApi { // (undocumented) @@ -486,9 +427,7 @@ export class LocalStorageFeatureFlags implements FeatureFlagsApi { save(options: FeatureFlagsSaveOptions): void; } -// Warning: (ae-missing-release-tag) "MicrosoftAuth" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export class MicrosoftAuth { // (undocumented) static create({ @@ -500,17 +439,13 @@ export class MicrosoftAuth { }: OAuthApiCreateOptions): typeof microsoftAuthApiRef.T; } -// Warning: (ae-missing-release-tag) "NoOpAnalyticsApi" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export class NoOpAnalyticsApi implements AnalyticsApi { // (undocumented) captureEvent(_event: AnalyticsEvent): void; } -// Warning: (ae-missing-release-tag) "OAuth2" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export class OAuth2 implements OAuthApi, @@ -519,8 +454,10 @@ export class OAuth2 BackstageIdentityApi, SessionApi { - // Warning: (ae-forgotten-export) The symbol "Options" needs to be exported by the entry point index.d.ts - constructor(options: Options); + constructor(options: { + sessionManager: SessionManager; + scopeTransform: (scopes: string[]) => string[]; + }); // Warning: (ae-forgotten-export) The symbol "CreateOptions" needs to be exported by the entry point index.d.ts // // (undocumented) @@ -553,9 +490,7 @@ export class OAuth2 signOut(): Promise; } -// Warning: (ae-missing-release-tag) "OAuth2Session" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export type OAuth2Session = { providerInfo: { idToken: string; @@ -567,8 +502,6 @@ export type OAuth2Session = { backstageIdentity: BackstageIdentity; }; -// Warning: (ae-missing-release-tag) "OAuthRequestManager" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export class OAuthRequestManager implements OAuthRequestApi { // (undocumented) @@ -577,9 +510,7 @@ export class OAuthRequestManager implements OAuthRequestApi { createAuthRequester(options: AuthRequesterOptions): AuthRequester; } -// Warning: (ae-missing-release-tag) "OktaAuth" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export class OktaAuth { // (undocumented) static create({ @@ -591,9 +522,7 @@ export class OktaAuth { }: OAuthApiCreateOptions): typeof oktaAuthApiRef.T; } -// Warning: (ae-missing-release-tag) "OneLoginAuth" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export class OneLoginAuth { // Warning: (ae-forgotten-export) The symbol "CreateOptions" needs to be exported by the entry point index.d.ts // @@ -606,9 +535,7 @@ export class OneLoginAuth { }: CreateOptions_2): typeof oneloginAuthApiRef.T; } -// Warning: (ae-missing-release-tag) "SamlAuth" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export class SamlAuth implements ProfileInfoApi, BackstageIdentityApi, SessionApi { @@ -636,16 +563,12 @@ export class SamlAuth signOut(): Promise; } -// Warning: (ae-missing-release-tag) "SignInPageProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export type SignInPageProps = { onResult(result: SignInResult): void; }; -// Warning: (ae-missing-release-tag) "SignInResult" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export type SignInResult = { userId: string; profile: ProfileInfo; @@ -653,15 +576,11 @@ export type SignInResult = { signOut?: () => Promise; }; -// Warning: (ae-missing-release-tag) "UnhandledErrorForwarder" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export class UnhandledErrorForwarder { static forward(errorApi: ErrorApi, errorContext: ErrorContext): void; } -// Warning: (ae-missing-release-tag) "UrlPatternDiscovery" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export class UrlPatternDiscovery implements DiscoveryApi { static compile(pattern: string): UrlPatternDiscovery; @@ -669,15 +588,14 @@ export class UrlPatternDiscovery implements DiscoveryApi { getBaseUrl(pluginId: string): Promise; } -// Warning: (ae-missing-release-tag) "WebStorage" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export class WebStorage implements StorageApi { constructor(namespace: string, errorApi: ErrorApi); - // Warning: (ae-forgotten-export) The symbol "CreateStorageApiOptions" needs to be exported by the entry point index.d.ts - // // (undocumented) - static create(options: CreateStorageApiOptions): WebStorage; + static create(options: { + errorApi: ErrorApi; + namespace?: string; + }): WebStorage; // (undocumented) forBucket(name: string): WebStorage; // (undocumented) @@ -692,7 +610,6 @@ export class WebStorage implements StorageApi { // Warnings were encountered during analysis: // -// src/apis/system/ApiProvider.d.ts:9:5 - (ae-forgotten-export) The symbol "ApiProviderProps" needs to be exported by the entry point index.d.ts -// src/app/types.d.ts:89:5 - (ae-forgotten-export) The symbol "UnknownPluginOutput" needs to be exported by the entry point index.d.ts -// src/app/types.d.ts:100:5 - (ae-forgotten-export) The symbol "AppIcons" needs to be exported by the entry point index.d.ts +// src/apis/system/ApiProvider.d.ts:15:5 - (ae-forgotten-export) The symbol "ApiProviderProps" needs to be exported by the entry point index.d.ts +// src/app/types.d.ts:152:5 - (ae-forgotten-export) The symbol "AppIcons" needs to be exported by the entry point index.d.ts ``` diff --git a/packages/core-app-api/package.json b/packages/core-app-api/package.json index aee8eb9f02..f40e3d5eb7 100644 --- a/packages/core-app-api/package.json +++ b/packages/core-app-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-app-api", "description": "Core app API used by Backstage apps", - "version": "0.1.18", + "version": "0.1.19", "private": false, "publishConfig": { "access": "public", @@ -29,10 +29,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-components": "^0.7.1", - "@backstage/config": "^0.1.10", - "@backstage/core-plugin-api": "^0.1.11", - "@backstage/theme": "^0.2.11", + "@backstage/core-components": "^0.7.2", + "@backstage/config": "^0.1.11", + "@backstage/core-plugin-api": "^0.1.12", + "@backstage/theme": "^0.2.12", "@backstage/types": "^0.1.1", "@backstage/version-bridge": "^0.1.0", "@material-ui/core": "^4.12.2", @@ -46,8 +46,8 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.8.0", - "@backstage/test-utils": "^0.1.19", + "@backstage/cli": "^0.8.1", + "@backstage/test-utils": "^0.1.20", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", @@ -56,7 +56,7 @@ "@types/node": "^14.14.32", "@types/zen-observable": "^0.8.0", "cross-fetch": "^3.0.6", - "msw": "^0.29.0" + "msw": "^0.35.0" }, "files": [ "dist", diff --git a/packages/core-app-api/src/apis/implementations/AlertApi/AlertApiForwarder.ts b/packages/core-app-api/src/apis/implementations/AlertApi/AlertApiForwarder.ts index 5e649e2f4c..4e5397f65d 100644 --- a/packages/core-app-api/src/apis/implementations/AlertApi/AlertApiForwarder.ts +++ b/packages/core-app-api/src/apis/implementations/AlertApi/AlertApiForwarder.ts @@ -20,6 +20,8 @@ import { PublishSubject } from '../../../lib/subjects'; /** * Base implementation for the AlertApi that simply forwards alerts to consumers. + * + * @public */ export class AlertApiForwarder implements AlertApi { private readonly subject = new PublishSubject(); diff --git a/packages/core-app-api/src/apis/implementations/AnalyticsApi/NoOpAnalyticsApi.ts b/packages/core-app-api/src/apis/implementations/AnalyticsApi/NoOpAnalyticsApi.ts index a3e45006ba..fb324465ca 100644 --- a/packages/core-app-api/src/apis/implementations/AnalyticsApi/NoOpAnalyticsApi.ts +++ b/packages/core-app-api/src/apis/implementations/AnalyticsApi/NoOpAnalyticsApi.ts @@ -17,6 +17,8 @@ import { AnalyticsApi, AnalyticsEvent } from '@backstage/core-plugin-api'; /** * Base implementation for the AnalyticsApi that does nothing. + * + * @public */ export class NoOpAnalyticsApi implements AnalyticsApi { captureEvent(_event: AnalyticsEvent): void {} diff --git a/packages/core-app-api/src/apis/implementations/AppThemeApi/AppThemeSelector.ts b/packages/core-app-api/src/apis/implementations/AppThemeApi/AppThemeSelector.ts index 3dfa43b661..b0303cf29a 100644 --- a/packages/core-app-api/src/apis/implementations/AppThemeApi/AppThemeSelector.ts +++ b/packages/core-app-api/src/apis/implementations/AppThemeApi/AppThemeSelector.ts @@ -20,6 +20,12 @@ import { BehaviorSubject } from '../../../lib/subjects'; const STORAGE_KEY = 'theme'; +/** + * Exposes the themes installed in the app, and permits switching the currently + * active theme. + * + * @public + */ export class AppThemeSelector implements AppThemeApi { static createWithStorage(themes: AppTheme[]) { const selector = new AppThemeSelector(themes); diff --git a/packages/core-app-api/src/apis/implementations/DiscoveryApi/UrlPatternDiscovery.ts b/packages/core-app-api/src/apis/implementations/DiscoveryApi/UrlPatternDiscovery.ts index 58e14c9f04..aa921c2595 100644 --- a/packages/core-app-api/src/apis/implementations/DiscoveryApi/UrlPatternDiscovery.ts +++ b/packages/core-app-api/src/apis/implementations/DiscoveryApi/UrlPatternDiscovery.ts @@ -21,6 +21,8 @@ const ERROR_PREFIX = 'Invalid discovery URL pattern,'; /** * UrlPatternDiscovery is a lightweight DiscoveryApi implementation. * It uses a single template string to construct URLs for each plugin. + * + * @public */ export class UrlPatternDiscovery implements DiscoveryApi { /** diff --git a/packages/core-app-api/src/apis/implementations/ErrorApi/ErrorAlerter.ts b/packages/core-app-api/src/apis/implementations/ErrorApi/ErrorAlerter.ts index 57f1ffab66..2111798d6a 100644 --- a/packages/core-app-api/src/apis/implementations/ErrorApi/ErrorAlerter.ts +++ b/packages/core-app-api/src/apis/implementations/ErrorApi/ErrorAlerter.ts @@ -18,6 +18,8 @@ import { ErrorApi, ErrorContext, AlertApi } from '@backstage/core-plugin-api'; /** * Decorates an ErrorApi by also forwarding error messages * to the alertApi with an 'error' severity. + * + * @public */ export class ErrorAlerter implements ErrorApi { constructor( diff --git a/packages/core-app-api/src/apis/implementations/ErrorApi/ErrorApiForwarder.ts b/packages/core-app-api/src/apis/implementations/ErrorApi/ErrorApiForwarder.ts index 0edbd2f353..cd4564a050 100644 --- a/packages/core-app-api/src/apis/implementations/ErrorApi/ErrorApiForwarder.ts +++ b/packages/core-app-api/src/apis/implementations/ErrorApi/ErrorApiForwarder.ts @@ -20,6 +20,8 @@ import { PublishSubject } from '../../../lib/subjects'; /** * Base implementation for the ErrorApi that simply forwards errors to consumers. + * + * @public */ export class ErrorApiForwarder implements ErrorApi { private readonly subject = new PublishSubject<{ diff --git a/packages/core-app-api/src/apis/implementations/ErrorApi/UnhandledErrorForwarder.ts b/packages/core-app-api/src/apis/implementations/ErrorApi/UnhandledErrorForwarder.ts index b859148e8e..16e473fb3a 100644 --- a/packages/core-app-api/src/apis/implementations/ErrorApi/UnhandledErrorForwarder.ts +++ b/packages/core-app-api/src/apis/implementations/ErrorApi/UnhandledErrorForwarder.ts @@ -16,6 +16,11 @@ import { ErrorApi, ErrorContext } from '@backstage/core-plugin-api'; * limitations under the License. */ +/** + * Utility class that helps with error forwarding. + * + * @public + */ export class UnhandledErrorForwarder { /** * Add event listener, such that unhandled errors can be forwarded using an given `ErrorApi` instance diff --git a/packages/core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags.tsx b/packages/core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags.tsx index 3ee62b3d6e..2c8470642a 100644 --- a/packages/core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags.tsx +++ b/packages/core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags.tsx @@ -43,7 +43,10 @@ export function validateFlagName(name: string): void { } /** - * Create the FeatureFlags implementation based on the API. + * A feature flags implementation that stores the flags in the browser's local + * storage. + * + * @public */ export class LocalStorageFeatureFlags implements FeatureFlagsApi { private registeredFeatureFlags: FeatureFlag[] = []; diff --git a/packages/core-app-api/src/apis/implementations/OAuthRequestApi/OAuthRequestManager.ts b/packages/core-app-api/src/apis/implementations/OAuthRequestApi/OAuthRequestManager.ts index 1cd25c4b56..7e7f3c2507 100644 --- a/packages/core-app-api/src/apis/implementations/OAuthRequestApi/OAuthRequestManager.ts +++ b/packages/core-app-api/src/apis/implementations/OAuthRequestApi/OAuthRequestManager.ts @@ -30,6 +30,8 @@ import { BehaviorSubject } from '../../../lib/subjects'; * The purpose of this class and the API is to read a stream of incoming requests * of OAuth access tokens from different providers with varying scope, and funnel * them all together into a single request for each OAuth provider. + * + * @public */ export class OAuthRequestManager implements OAuthRequestApi { private readonly subject = new BehaviorSubject([]); diff --git a/packages/core-app-api/src/apis/implementations/StorageApi/WebStorage.test.ts b/packages/core-app-api/src/apis/implementations/StorageApi/WebStorage.test.ts index 6ae43b6100..f8dd85c05c 100644 --- a/packages/core-app-api/src/apis/implementations/StorageApi/WebStorage.test.ts +++ b/packages/core-app-api/src/apis/implementations/StorageApi/WebStorage.test.ts @@ -13,13 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { CreateStorageApiOptions, WebStorage } from './WebStorage'; -import { StorageApi } from '@backstage/core-plugin-api'; +import { WebStorage } from './WebStorage'; +import { ErrorApi, StorageApi } from '@backstage/core-plugin-api'; describe('WebStorage Storage API', () => { const mockErrorApi = { post: jest.fn(), error$: jest.fn() }; const createWebStorage = ( - args?: Partial, + args?: Partial<{ + errorApi: ErrorApi; + namespace?: string; + }>, ): StorageApi => { return WebStorage.create({ errorApi: mockErrorApi, diff --git a/packages/core-app-api/src/apis/implementations/StorageApi/WebStorage.ts b/packages/core-app-api/src/apis/implementations/StorageApi/WebStorage.ts index 08c4df7e8c..b252e6b726 100644 --- a/packages/core-app-api/src/apis/implementations/StorageApi/WebStorage.ts +++ b/packages/core-app-api/src/apis/implementations/StorageApi/WebStorage.ts @@ -24,18 +24,21 @@ import ObservableImpl from 'zen-observable'; const buckets = new Map(); -export type CreateStorageApiOptions = { - errorApi: ErrorApi; - namespace?: string; -}; - +/** + * An implementation of the storage API, that uses the browser's local storage. + * + * @public + */ export class WebStorage implements StorageApi { constructor( private readonly namespace: string, private readonly errorApi: ErrorApi, ) {} - static create(options: CreateStorageApiOptions): WebStorage { + static create(options: { + errorApi: ErrorApi; + namespace?: string; + }): WebStorage { return new WebStorage(options.namespace ?? '', options.errorApi); } diff --git a/packages/core-app-api/src/apis/implementations/auth/atlassian/AtlassianAuth.ts b/packages/core-app-api/src/apis/implementations/auth/atlassian/AtlassianAuth.ts index 423c45bc6c..227d70e494 100644 --- a/packages/core-app-api/src/apis/implementations/auth/atlassian/AtlassianAuth.ts +++ b/packages/core-app-api/src/apis/implementations/auth/atlassian/AtlassianAuth.ts @@ -25,7 +25,12 @@ const DEFAULT_PROVIDER = { icon: AtlassianIcon, }; -class AtlassianAuth { +/** + * Implements the OAuth flow to Atlassian products. + * + * @public + */ +export default class AtlassianAuth { static create({ discoveryApi, environment = 'development', @@ -40,5 +45,3 @@ class AtlassianAuth { }); } } - -export default AtlassianAuth; diff --git a/packages/core-app-api/src/apis/implementations/auth/auth0/Auth0Auth.ts b/packages/core-app-api/src/apis/implementations/auth/auth0/Auth0Auth.ts index 5f074252bf..69462942e4 100644 --- a/packages/core-app-api/src/apis/implementations/auth/auth0/Auth0Auth.ts +++ b/packages/core-app-api/src/apis/implementations/auth/auth0/Auth0Auth.ts @@ -25,7 +25,12 @@ const DEFAULT_PROVIDER = { icon: Auth0Icon, }; -class Auth0Auth { +/** + * Implements the OAuth flow to Auth0 products. + * + * @public + */ +export default class Auth0Auth { static create({ discoveryApi, environment = 'development', @@ -42,5 +47,3 @@ class Auth0Auth { }); } } - -export default Auth0Auth; diff --git a/packages/core-app-api/src/apis/implementations/auth/bitbucket/BitbucketAuth.ts b/packages/core-app-api/src/apis/implementations/auth/bitbucket/BitbucketAuth.ts index c88db2a2b0..c9db93906a 100644 --- a/packages/core-app-api/src/apis/implementations/auth/bitbucket/BitbucketAuth.ts +++ b/packages/core-app-api/src/apis/implementations/auth/bitbucket/BitbucketAuth.ts @@ -40,7 +40,12 @@ const DEFAULT_PROVIDER = { icon: BitbucketIcon, }; -class BitbucketAuth { +/** + * Implements the OAuth flow to Bitbucket products. + * + * @public + */ +export default class BitbucketAuth { static create({ discoveryApi, environment = 'development', @@ -57,5 +62,3 @@ class BitbucketAuth { }); } } - -export default BitbucketAuth; diff --git a/packages/core-app-api/src/apis/implementations/auth/bitbucket/types.ts b/packages/core-app-api/src/apis/implementations/auth/bitbucket/types.ts index 7babfdf686..5309fffcd8 100644 --- a/packages/core-app-api/src/apis/implementations/auth/bitbucket/types.ts +++ b/packages/core-app-api/src/apis/implementations/auth/bitbucket/types.ts @@ -16,6 +16,11 @@ import { ProfileInfo, BackstageIdentity } from '@backstage/core-plugin-api'; +/** + * Session information for Bitbucket auth. + * + * @public + */ export type BitbucketSession = { providerInfo: { accessToken: string; diff --git a/packages/core-app-api/src/apis/implementations/auth/github/GithubAuth.ts b/packages/core-app-api/src/apis/implementations/auth/github/GithubAuth.ts index 72b4209a34..01e7e77b8e 100644 --- a/packages/core-app-api/src/apis/implementations/auth/github/GithubAuth.ts +++ b/packages/core-app-api/src/apis/implementations/auth/github/GithubAuth.ts @@ -51,7 +51,12 @@ const DEFAULT_PROVIDER = { icon: GithubIcon, }; -class GithubAuth implements OAuthApi, SessionApi { +/** + * Implements the OAuth flow to GitHub products. + * + * @public + */ +export default class GithubAuth implements OAuthApi, SessionApi { static create({ discoveryApi, environment = 'development', @@ -158,4 +163,3 @@ class GithubAuth implements OAuthApi, SessionApi { return new Set(scopeList); } } -export default GithubAuth; diff --git a/packages/core-app-api/src/apis/implementations/auth/github/types.ts b/packages/core-app-api/src/apis/implementations/auth/github/types.ts index f5dae3a064..e1c88b9173 100644 --- a/packages/core-app-api/src/apis/implementations/auth/github/types.ts +++ b/packages/core-app-api/src/apis/implementations/auth/github/types.ts @@ -16,6 +16,11 @@ import { ProfileInfo, BackstageIdentity } from '@backstage/core-plugin-api'; +/** + * Session information for GitHub auth. + * + * @public + */ export type GithubSession = { providerInfo: { accessToken: string; diff --git a/packages/core-app-api/src/apis/implementations/auth/gitlab/GitlabAuth.ts b/packages/core-app-api/src/apis/implementations/auth/gitlab/GitlabAuth.ts index 642600558c..af581d0018 100644 --- a/packages/core-app-api/src/apis/implementations/auth/gitlab/GitlabAuth.ts +++ b/packages/core-app-api/src/apis/implementations/auth/gitlab/GitlabAuth.ts @@ -25,7 +25,12 @@ const DEFAULT_PROVIDER = { icon: GitlabIcon, }; -class GitlabAuth { +/** + * Implements the OAuth flow to GitLab products. + * + * @public + */ +export default class GitlabAuth { static create({ discoveryApi, environment = 'development', @@ -42,4 +47,3 @@ class GitlabAuth { }); } } -export default GitlabAuth; diff --git a/packages/core-app-api/src/apis/implementations/auth/google/GoogleAuth.ts b/packages/core-app-api/src/apis/implementations/auth/google/GoogleAuth.ts index 39e4a896e4..916c52382e 100644 --- a/packages/core-app-api/src/apis/implementations/auth/google/GoogleAuth.ts +++ b/packages/core-app-api/src/apis/implementations/auth/google/GoogleAuth.ts @@ -27,7 +27,12 @@ const DEFAULT_PROVIDER = { const SCOPE_PREFIX = 'https://www.googleapis.com/auth/'; -class GoogleAuth { +/** + * Implements the OAuth flow to Google products. + * + * @public + */ +export default class GoogleAuth { static create({ discoveryApi, oauthRequestApi, @@ -65,4 +70,3 @@ class GoogleAuth { }); } } -export default GoogleAuth; diff --git a/packages/core-app-api/src/apis/implementations/auth/microsoft/MicrosoftAuth.ts b/packages/core-app-api/src/apis/implementations/auth/microsoft/MicrosoftAuth.ts index b0f7f42a10..09bd7f67a2 100644 --- a/packages/core-app-api/src/apis/implementations/auth/microsoft/MicrosoftAuth.ts +++ b/packages/core-app-api/src/apis/implementations/auth/microsoft/MicrosoftAuth.ts @@ -25,7 +25,12 @@ const DEFAULT_PROVIDER = { icon: MicrosoftIcon, }; -class MicrosoftAuth { +/** + * Implements the OAuth flow to Microsoft products. + * + * @public + */ +export default class MicrosoftAuth { static create({ environment = 'development', provider = DEFAULT_PROVIDER, @@ -48,5 +53,3 @@ class MicrosoftAuth { }); } } - -export default MicrosoftAuth; diff --git a/packages/core-app-api/src/apis/implementations/auth/oauth2/OAuth2.ts b/packages/core-app-api/src/apis/implementations/auth/oauth2/OAuth2.ts index 8f685b9266..6c0759d967 100644 --- a/packages/core-app-api/src/apis/implementations/auth/oauth2/OAuth2.ts +++ b/packages/core-app-api/src/apis/implementations/auth/oauth2/OAuth2.ts @@ -33,11 +33,6 @@ import { Observable } from '@backstage/types'; import { OAuth2Session } from './types'; import { OAuthApiCreateOptions } from '../types'; -type Options = { - sessionManager: SessionManager; - scopeTransform: (scopes: string[]) => string[]; -}; - type CreateOptions = OAuthApiCreateOptions & { scopeTransform?: (scopes: string[]) => string[]; }; @@ -59,7 +54,12 @@ const DEFAULT_PROVIDER = { icon: OAuth2Icon, }; -class OAuth2 +/** + * Implements a generic OAuth2 flow for auth. + * + * @public + */ +export default class OAuth2 implements OAuthApi, OpenIdConnectApi, @@ -115,7 +115,10 @@ class OAuth2 private readonly sessionManager: SessionManager; private readonly scopeTransform: (scopes: string[]) => string[]; - constructor(options: Options) { + constructor(options: { + sessionManager: SessionManager; + scopeTransform: (scopes: string[]) => string[]; + }) { this.sessionManager = options.sessionManager; this.scopeTransform = options.scopeTransform; } @@ -176,5 +179,3 @@ class OAuth2 return new Set(scopeTransform(scopeList)); } } - -export default OAuth2; diff --git a/packages/core-app-api/src/apis/implementations/auth/oauth2/types.ts b/packages/core-app-api/src/apis/implementations/auth/oauth2/types.ts index be0fbf38a2..4ada35846a 100644 --- a/packages/core-app-api/src/apis/implementations/auth/oauth2/types.ts +++ b/packages/core-app-api/src/apis/implementations/auth/oauth2/types.ts @@ -16,6 +16,11 @@ import { ProfileInfo, BackstageIdentity } from '@backstage/core-plugin-api'; +/** + * Session information for generic OAuth2 auth. + * + * @public + */ export type OAuth2Session = { providerInfo: { idToken: string; diff --git a/packages/core-app-api/src/apis/implementations/auth/okta/OktaAuth.ts b/packages/core-app-api/src/apis/implementations/auth/okta/OktaAuth.ts index 5ef9bf04a0..294fb496af 100644 --- a/packages/core-app-api/src/apis/implementations/auth/okta/OktaAuth.ts +++ b/packages/core-app-api/src/apis/implementations/auth/okta/OktaAuth.ts @@ -37,7 +37,12 @@ const OKTA_OIDC_SCOPES: Set = new Set([ const OKTA_SCOPE_PREFIX: string = 'okta.'; -class OktaAuth { +/** + * Implements the OAuth flow to Okta products. + * + * @public + */ +export default class OktaAuth { static create({ discoveryApi, environment = 'development', @@ -67,5 +72,3 @@ class OktaAuth { }); } } - -export default OktaAuth; diff --git a/packages/core-app-api/src/apis/implementations/auth/onelogin/OneLoginAuth.ts b/packages/core-app-api/src/apis/implementations/auth/onelogin/OneLoginAuth.ts index bb0aebae94..f49ea4cde8 100644 --- a/packages/core-app-api/src/apis/implementations/auth/onelogin/OneLoginAuth.ts +++ b/packages/core-app-api/src/apis/implementations/auth/onelogin/OneLoginAuth.ts @@ -26,7 +26,6 @@ import { OAuth2 } from '../oauth2'; type CreateOptions = { discoveryApi: DiscoveryApi; oauthRequestApi: OAuthRequestApi; - environment?: string; provider?: AuthProvider & { id: string }; }; @@ -49,7 +48,12 @@ const OIDC_SCOPES: Set = new Set([ const SCOPE_PREFIX: string = 'onelogin.'; -class OneLoginAuth { +/** + * Implements a OneLogin OAuth flow. + * + * @public + */ +export default class OneLoginAuth { static create({ discoveryApi, environment = 'development', @@ -78,5 +82,3 @@ class OneLoginAuth { }); } } - -export default OneLoginAuth; diff --git a/packages/core-app-api/src/apis/implementations/auth/saml/SamlAuth.ts b/packages/core-app-api/src/apis/implementations/auth/saml/SamlAuth.ts index 0a7fb50101..f2668dedd2 100644 --- a/packages/core-app-api/src/apis/implementations/auth/saml/SamlAuth.ts +++ b/packages/core-app-api/src/apis/implementations/auth/saml/SamlAuth.ts @@ -45,7 +45,14 @@ const DEFAULT_PROVIDER = { icon: SamlIcon, }; -class SamlAuth implements ProfileInfoApi, BackstageIdentityApi, SessionApi { +/** + * Implements a general SAML based auth flow. + * + * @public + */ +export default class SamlAuth + implements ProfileInfoApi, BackstageIdentityApi, SessionApi +{ static create({ discoveryApi, environment = 'development', @@ -94,5 +101,3 @@ class SamlAuth implements ProfileInfoApi, BackstageIdentityApi, SessionApi { return session?.profile; } } - -export default SamlAuth; diff --git a/packages/core-app-api/src/apis/implementations/auth/saml/types.ts b/packages/core-app-api/src/apis/implementations/auth/saml/types.ts index 70cbf41ee4..724f0aa5d5 100644 --- a/packages/core-app-api/src/apis/implementations/auth/saml/types.ts +++ b/packages/core-app-api/src/apis/implementations/auth/saml/types.ts @@ -15,6 +15,11 @@ */ import { ProfileInfo, BackstageIdentity } from '@backstage/core-plugin-api'; +/** + * Session information for SAML auth. + * + * @public + */ export type SamlSession = { userId: string; profile: ProfileInfo; diff --git a/packages/core-app-api/src/apis/system/ApiFactoryRegistry.ts b/packages/core-app-api/src/apis/system/ApiFactoryRegistry.ts index 28ed9f85a1..880f075930 100644 --- a/packages/core-app-api/src/apis/system/ApiFactoryRegistry.ts +++ b/packages/core-app-api/src/apis/system/ApiFactoryRegistry.ts @@ -44,6 +44,8 @@ type FactoryTuple = { * * Each scope has an assigned priority, where factories registered with * higher priority scopes override ones with lower priority. + * + * @public */ export class ApiFactoryRegistry implements ApiFactoryHolder { private readonly factories = new Map(); diff --git a/packages/core-app-api/src/apis/system/ApiProvider.tsx b/packages/core-app-api/src/apis/system/ApiProvider.tsx index aa57fa9310..73bbdd6f77 100644 --- a/packages/core-app-api/src/apis/system/ApiProvider.tsx +++ b/packages/core-app-api/src/apis/system/ApiProvider.tsx @@ -30,10 +30,14 @@ type ApiProviderProps = { const ApiContext = createVersionedContext<{ 1: ApiHolder }>('api-context'); -export const ApiProvider = ({ - apis, - children, -}: PropsWithChildren) => { +/** + * Provides an {@link @backstage/core-plugin-api#ApiHolder} for consumption in + * the React tree. + * + * @public + */ +export const ApiProvider = (props: PropsWithChildren) => { + const { apis, children } = props; const parentHolder = useContext(ApiContext)?.atVersion(1); const holder = parentHolder ? new ApiAggregator(apis, parentHolder) : apis; diff --git a/packages/core-app-api/src/apis/system/ApiRegistry.ts b/packages/core-app-api/src/apis/system/ApiRegistry.ts index 7669810a1e..29c8b1cfe4 100644 --- a/packages/core-app-api/src/apis/system/ApiRegistry.ts +++ b/packages/core-app-api/src/apis/system/ApiRegistry.ts @@ -32,11 +32,21 @@ class ApiRegistryBuilder { } } +/** + * A registry for utility APIs. + * + * @public + */ export class ApiRegistry implements ApiHolder { static builder() { return new ApiRegistryBuilder(); } + /** + * Creates a new ApiRegistry with a list of API implementations. + * + * @param apis - A list of pairs mapping an ApiRef to its respective implementation + */ static from(apis: ApiImpl[]) { return new ApiRegistry(new Map(apis.map(([api, impl]) => [api.id, impl]))); } @@ -44,8 +54,8 @@ export class ApiRegistry implements ApiHolder { /** * Creates a new ApiRegistry with a single API implementation. * - * @param api ApiRef for the API to add - * @param impl Implementation of the API to add + * @param api - ApiRef for the API to add + * @param impl - Implementation of the API to add */ static with(api: ApiRef, impl: T): ApiRegistry { return new ApiRegistry(new Map([[api.id, impl]])); @@ -56,8 +66,8 @@ export class ApiRegistry implements ApiHolder { /** * Returns a new ApiRegistry with the provided API added to the existing ones. * - * @param api ApiRef for the API to add - * @param impl Implementation of the API to add + * @param api - ApiRef for the API to add + * @param impl - Implementation of the API to add */ with(api: ApiRef, impl: T): ApiRegistry { return new ApiRegistry(new Map([...this.apis, [api.id, impl]])); diff --git a/packages/core-app-api/src/apis/system/ApiResolver.ts b/packages/core-app-api/src/apis/system/ApiResolver.ts index dd29ff5010..0c050ebc30 100644 --- a/packages/core-app-api/src/apis/system/ApiResolver.ts +++ b/packages/core-app-api/src/apis/system/ApiResolver.ts @@ -22,6 +22,12 @@ import { } from '@backstage/core-plugin-api'; import { ApiFactoryHolder } from './types'; +/** + * Handles the actual on-demand instantiation and memoization of APIs out of + * an {@link ApiFactoryHolder}. + * + * @public + */ export class ApiResolver implements ApiHolder { /** * Validate factories by making sure that each of the apis can be created diff --git a/packages/core-app-api/src/apis/system/types.ts b/packages/core-app-api/src/apis/system/types.ts index bb0b9d42ea..de4b7cb699 100644 --- a/packages/core-app-api/src/apis/system/types.ts +++ b/packages/core-app-api/src/apis/system/types.ts @@ -16,6 +16,9 @@ import { ApiFactory, ApiRef } from '@backstage/core-plugin-api'; +/** + * @public + */ export type ApiFactoryHolder = { get( api: ApiRef, diff --git a/packages/core-app-api/src/app/createApp.tsx b/packages/core-app-api/src/app/createApp.tsx index 901697edba..65aa15b50c 100644 --- a/packages/core-app-api/src/app/createApp.tsx +++ b/packages/core-app-api/src/app/createApp.tsx @@ -48,6 +48,8 @@ import { BackstagePlugin } from '@backstage/core-plugin-api'; * which can be rewritten at runtime to contain an additional JSON config object. * If runtime config is present, it will be placed first in the config array, overriding * other config values. + * + * @public */ export const defaultConfigLoader: AppConfigLoader = async ( // This string may be replaced at runtime to provide additional config. @@ -100,6 +102,8 @@ export function OptionallyWrapInRouter({ children }: PropsWithChildren<{}>) { /** * Creates a new Backstage App. + * + * @public */ export function createApp(options?: AppOptions) { const DefaultNotFoundPage = () => ( diff --git a/packages/core-app-api/src/app/types.ts b/packages/core-app-api/src/app/types.ts index 09121f8105..407018111b 100644 --- a/packages/core-app-api/src/app/types.ts +++ b/packages/core-app-api/src/app/types.ts @@ -29,11 +29,21 @@ import { import { AppConfig } from '@backstage/config'; import { AppIcons } from './icons'; +/** + * Props for the `BootErrorPage` component of {@link AppComponents}. + * + * @public + */ export type BootErrorPageProps = { step: 'load-config' | 'load-chunk'; error: Error; }; +/** + * The outcome of signing in on the sign-in page. + * + * @public + */ export type SignInResult = { /** * User ID that will be returned by the IdentityApi @@ -53,6 +63,11 @@ export type SignInResult = { signOut?: () => Promise; }; +/** + * Props for the `SignInPage` component of {@link AppComponents}. + * + * @public + */ export type SignInPageProps = { /** * Set the sign-in result for the app. This should only be called once. @@ -60,12 +75,22 @@ export type SignInPageProps = { onResult(result: SignInResult): void; }; +/** + * Props for the fallback error boundary. + * + * @public + */ export type ErrorBoundaryFallbackProps = { plugin?: BackstagePlugin; error: Error; resetError: () => void; }; +/** + * A set of replaceable core components that are part of every Backstage app. + * + * @public + */ export type AppComponents = { NotFoundErrorPage: ComponentType<{}>; BootErrorPage: ComponentType; @@ -91,6 +116,8 @@ export type AppComponents = { * * If multiple config objects are returned in the array, values in the earlier configs * will override later ones. + * + * @public */ export type AppConfigLoader = () => Promise; @@ -123,6 +150,12 @@ type TargetRouteMap< : never; }; +/** + * A function that can bind from external routes of a given plugin, to concrete + * routes of other plugins. See {@link createApp}. + * + * @public + */ export type AppRouteBinder = < ExternalRoutes extends { [name: string]: ExternalRouteRef }, >( @@ -133,21 +166,33 @@ export type AppRouteBinder = < >, ) => void; -// Output from newer or older plugin API versions that might not be supported by -// this version of the app API, but we don't want to break at the type checking level. -// We only use this more permissive type for the `createApp` options, as we otherwise -// want to stick to using the type for the outputs that we know about in this version -// of the app api. -type UnknownPluginOutput = { - type: string; -}; +/** + * Internal helper type that represents a plugin with any type of output. + * + * @public + * @remarks + * + * The `type: string` type is there to handle output from newer or older plugin + * API versions that might not be supported by this version of the app API, but + * we don't want to break at the type checking level. We only use this more + * permissive type for the `createApp` options, as we otherwise want to stick + * to using the type for the outputs that we know about in this version of the + * app api. + * + * TODO(freben): This should be marked internal but that's not supported by the api report generation tools yet + */ export type BackstagePluginWithAnyOutput = Omit< BackstagePlugin, 'output' > & { - output(): (PluginOutput | UnknownPluginOutput)[]; + output(): (PluginOutput | { type: string })[]; }; +/** + * The options accepted by {@link createApp}. + * + * @public + */ export type AppOptions = { /** * A collection of ApiFactories to register in the application to either @@ -226,6 +271,11 @@ export type AppOptions = { bindRoutes?(context: { bind: AppRouteBinder }): void; }; +/** + * The public API of the output of {@link createApp}. + * + * @public + */ export type BackstageApp = { /** * Returns all plugins registered for the app. @@ -250,6 +300,12 @@ export type BackstageApp = { getRouter(): ComponentType<{}>; }; +/** + * The central context providing runtime app specific state that plugin views + * want to consume. + * + * @public + */ export type AppContext = { /** * Get a list of all plugins that are installed in the app. diff --git a/packages/core-app-api/src/lib/AuthConnector/DefaultAuthConnector.test.ts b/packages/core-app-api/src/lib/AuthConnector/DefaultAuthConnector.test.ts index 28125f6fa8..7e448586e3 100644 --- a/packages/core-app-api/src/lib/AuthConnector/DefaultAuthConnector.test.ts +++ b/packages/core-app-api/src/lib/AuthConnector/DefaultAuthConnector.test.ts @@ -19,7 +19,7 @@ import { DefaultAuthConnector } from './DefaultAuthConnector'; import MockOAuthApi from '../../apis/implementations/OAuthRequestApi/MockOAuthApi'; import * as loginPopup from '../loginPopup'; import { UrlPatternDiscovery } from '../../apis'; -import { msw } from '@backstage/test-utils'; +import { setupRequestMockHandlers } from '@backstage/test-utils'; import { setupServer } from 'msw/node'; import { rest } from 'msw'; @@ -41,7 +41,7 @@ const defaultOptions = { describe('DefaultAuthConnector', () => { const server = setupServer(); - msw.setupDefaultHandlers(server); + setupRequestMockHandlers(server); afterEach(() => { jest.resetAllMocks(); diff --git a/packages/core-app-api/src/routing/FeatureFlagged.tsx b/packages/core-app-api/src/routing/FeatureFlagged.tsx index 47561d4135..2b0b5afe34 100644 --- a/packages/core-app-api/src/routing/FeatureFlagged.tsx +++ b/packages/core-app-api/src/routing/FeatureFlagged.tsx @@ -21,11 +21,22 @@ import { } from '@backstage/core-plugin-api'; import React, { ReactNode } from 'react'; +/** + * Props for the {@link FeatureFlagged} component. + * + * @public + */ export type FeatureFlaggedProps = { children: ReactNode } & ( | { with: string } | { without: string } ); +/** + * Enables or disables rendering of its children based on the state of a given + * feature flag. + * + * @public + */ export const FeatureFlagged = (props: FeatureFlaggedProps) => { const { children } = props; const featureFlagApi = useApi(featureFlagsApiRef); diff --git a/packages/core-app-api/src/routing/FlatRoutes.tsx b/packages/core-app-api/src/routing/FlatRoutes.tsx index 315ec91cdb..02dbc301fb 100644 --- a/packages/core-app-api/src/routing/FlatRoutes.tsx +++ b/packages/core-app-api/src/routing/FlatRoutes.tsx @@ -24,10 +24,26 @@ type RouteObject = { children?: RouteObject[]; }; -type FlatRoutesProps = { +/** + * Props for the {@link FlatRoutes} component. + * + * @public + */ +export type FlatRoutesProps = { children: ReactNode; }; +/** + * A wrapper around a set of routes. + * + * @remarks + * + * The root of the routing hierarchy in your app should use this component, + * instead of the one from `react-router-dom`. This ensures that all of the + * plugin route and utility API wiring happens under the hood. + * + * @public + */ export const FlatRoutes = (props: FlatRoutesProps): JSX.Element | null => { const app = useApp(); const { NotFoundErrorPage } = app.getComponents(); diff --git a/packages/core-app-api/src/routing/index.ts b/packages/core-app-api/src/routing/index.ts index 4169fffc88..46b5a6f9b4 100644 --- a/packages/core-app-api/src/routing/index.ts +++ b/packages/core-app-api/src/routing/index.ts @@ -15,5 +15,6 @@ */ export { FlatRoutes } from './FlatRoutes'; +export type { FlatRoutesProps } from './FlatRoutes'; export { FeatureFlagged } from './FeatureFlagged'; export type { FeatureFlaggedProps } from './FeatureFlagged'; diff --git a/packages/core-components/CHANGELOG.md b/packages/core-components/CHANGELOG.md index 375f23dfda..af03762094 100644 --- a/packages/core-components/CHANGELOG.md +++ b/packages/core-components/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/core-components +## 0.7.2 + +### Patch Changes + +- afd5c82ce1: Updates the d3 dependencies +- c6c2942daa: Deprecated `DismissbleBannerClassKey` and fixed the typo to make `DismissableBannerClassKey` +- Updated dependencies + - @backstage/config@0.1.11 + - @backstage/theme@0.2.12 + - @backstage/errors@0.1.4 + - @backstage/core-plugin-api@0.1.12 + ## 0.7.1 ### Patch Changes diff --git a/packages/core-components/package.json b/packages/core-components/package.json index 865f5b6df9..7f50af7488 100644 --- a/packages/core-components/package.json +++ b/packages/core-components/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-components", "description": "Core components used by Backstage plugins and apps", - "version": "0.7.1", + "version": "0.7.2", "private": false, "publishConfig": { "access": "public", @@ -29,10 +29,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/config": "^0.1.10", - "@backstage/core-plugin-api": "^0.1.11", - "@backstage/errors": "^0.1.3", - "@backstage/theme": "^0.2.11", + "@backstage/config": "^0.1.11", + "@backstage/core-plugin-api": "^0.1.12", + "@backstage/errors": "^0.1.4", + "@backstage/theme": "^0.2.12", "@material-table/core": "^3.1.0", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -42,9 +42,9 @@ "@types/react-text-truncate": "^0.14.0", "classnames": "^2.2.6", "clsx": "^1.1.0", - "d3-selection": "^2.0.0", - "d3-shape": "^2.0.0", - "d3-zoom": "^2.0.0", + "d3-selection": "^3.0.0", + "d3-shape": "^3.0.0", + "d3-zoom": "^3.0.0", "dagre": "^0.8.5", "immer": "^9.0.1", "lodash": "^4.17.21", @@ -67,17 +67,17 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/core-app-api": "^0.1.18", - "@backstage/cli": "^0.8.0", - "@backstage/test-utils": "^0.1.19", + "@backstage/core-app-api": "^0.1.19", + "@backstage/cli": "^0.8.1", + "@backstage/test-utils": "^0.1.20", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", "@testing-library/user-event": "^13.1.8", "@types/classnames": "^2.2.9", - "@types/d3-selection": "^2.0.0", + "@types/d3-selection": "^3.0.1", "@types/d3-shape": "^3.0.1", - "@types/d3-zoom": "^2.0.0", + "@types/d3-zoom": "^3.0.1", "@types/dagre": "^0.7.44", "@types/google-protobuf": "^3.7.2", "@types/jest": "^26.0.7", diff --git a/packages/core-plugin-api/CHANGELOG.md b/packages/core-plugin-api/CHANGELOG.md index 21ce590e1c..9d8246f931 100644 --- a/packages/core-plugin-api/CHANGELOG.md +++ b/packages/core-plugin-api/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/core-plugin-api +## 0.1.12 + +### Patch Changes + +- 41c49884d2: Start using the new `@backstage/types` package. Initially, this means using the `Observable` and `Json*` types from there. The types also remain in their old places but deprecated, and will be removed in a future release. +- 925a967f36: Replace usage of test-utils-core with test-utils +- Updated dependencies + - @backstage/config@0.1.11 + - @backstage/theme@0.2.12 + ## 0.1.11 ### Patch Changes diff --git a/packages/core-plugin-api/package.json b/packages/core-plugin-api/package.json index c59668a432..23bf0fc8b0 100644 --- a/packages/core-plugin-api/package.json +++ b/packages/core-plugin-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-plugin-api", "description": "Core API used by Backstage plugins", - "version": "0.1.11", + "version": "0.1.12", "private": false, "publishConfig": { "access": "public", @@ -29,8 +29,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/config": "^0.1.9", - "@backstage/theme": "^0.2.9", + "@backstage/config": "^0.1.11", + "@backstage/theme": "^0.2.12", "@backstage/types": "^0.1.1", "@backstage/version-bridge": "^0.1.0", "@material-ui/core": "^4.12.2", @@ -43,9 +43,9 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.8.0", - "@backstage/core-app-api": "^0.1.18", - "@backstage/test-utils": "^0.1.19", + "@backstage/cli": "^0.8.1", + "@backstage/core-app-api": "^0.1.19", + "@backstage/test-utils": "^0.1.20", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", @@ -55,7 +55,7 @@ "@types/prop-types": "^15.7.3", "@types/zen-observable": "^0.8.0", "cross-fetch": "^3.0.6", - "msw": "^0.29.0" + "msw": "^0.35.0" }, "files": [ "dist" diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index 070d558124..05e067ce2c 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/create-app +## 0.4.1 + +### Patch Changes + +- 4f1c30c176: Support optional path argument when generating a project using `create-app` +- Updated dependencies + - @backstage/cli-common@0.1.5 + ## 0.4.0 ### Minor Changes diff --git a/packages/create-app/package.json b/packages/create-app/package.json index 6cf606ed49..725f865435 100644 --- a/packages/create-app/package.json +++ b/packages/create-app/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/create-app", "description": "A CLI that helps you create your own Backstage app", - "version": "0.4.0", + "version": "0.4.1", "private": false, "publishConfig": { "access": "public" @@ -27,7 +27,7 @@ "start": "nodemon --" }, "dependencies": { - "@backstage/cli-common": "^0.1.4", + "@backstage/cli-common": "^0.1.5", "chalk": "^4.0.0", "commander": "^6.1.0", "fs-extra": "9.1.0", diff --git a/packages/create-app/src/createApp.ts b/packages/create-app/src/createApp.ts index 562ebf0e22..d9719742fb 100644 --- a/packages/create-app/src/createApp.ts +++ b/packages/create-app/src/createApp.ts @@ -27,7 +27,7 @@ import { Task, templatingTask } from './lib/tasks'; const exec = promisify(execCb); -async function checkExists(rootDir: string, name: string) { +async function checkAppExists(rootDir: string, name: string) { await Task.forItem('checking', name, async () => { const destination = resolvePath(rootDir, name); @@ -40,6 +40,17 @@ async function checkExists(rootDir: string, name: string) { }); } +async function checkPathExists(path: string) { + await Task.forItem('checking', path, async () => { + try { + await fs.mkdirs(path); + } catch (error) { + // will fail if a file already exists at given `path` + throw new Error(`Failed to create app directory: ${error.message}`); + } + }); +} + async function createTemporaryAppFolder(tempDir: string) { await Task.forItem('creating', 'temporary directory', async () => { try { @@ -50,12 +61,6 @@ async function createTemporaryAppFolder(tempDir: string) { }); } -async function cleanUp(tempDir: string) { - await Task.forItem('remove', 'temporary directory', async () => { - await fs.remove(tempDir); - }); -} - async function buildApp(appDir: string) { const runCmd = async (cmd: string) => { await Task.forItem('executing', cmd, async () => { @@ -75,11 +80,17 @@ async function buildApp(appDir: string) { async function moveApp(tempDir: string, destination: string, id: string) { await Task.forItem('moving', id, async () => { - await fs.move(tempDir, destination).catch(error => { - throw new Error( - `Failed to move app from ${tempDir} to ${destination}: ${error.message}`, - ); - }); + await fs + .move(tempDir, destination) + .catch(error => { + throw new Error( + `Failed to move app from ${tempDir} to ${destination}: ${error.message}`, + ); + }) + .finally(() => { + // remove temporary files on both success and failure + fs.removeSync(tempDir); + }); }); } @@ -117,23 +128,40 @@ export default async (cmd: Command): Promise => { const templateDir = paths.resolveOwn('templates/default-app'); const tempDir = resolvePath(os.tmpdir(), answers.name); - const appDir = resolvePath(paths.targetDir, answers.name); + + // Use `--path` argument as applicaiton directory when specified, otherwise + // create a directory using `answers.name` + const appDir = cmd.path + ? resolvePath(paths.targetDir, cmd.path) + : resolvePath(paths.targetDir, answers.name); Task.log(); Task.log('Creating the app...'); try { - Task.section('Checking if the directory is available'); - await checkExists(paths.targetDir, answers.name); + if (cmd.path) { + // Template directly to specified path - Task.section('Creating a temporary app directory'); - await createTemporaryAppFolder(tempDir); + Task.section('Checking that supplied path exists'); + await checkPathExists(appDir); - Task.section('Preparing files'); - await templatingTask(templateDir, tempDir, answers); + Task.section('Preparing files'); + await templatingTask(templateDir, cmd.path, answers); + } else { + // Template to temporary location, and then move files - Task.section('Moving to final location'); - await moveApp(tempDir, appDir, answers.name); + Task.section('Checking if the directory is available'); + await checkAppExists(paths.targetDir, answers.name); + + Task.section('Creating a temporary app directory'); + await createTemporaryAppFolder(tempDir); + + Task.section('Preparing files'); + await templatingTask(templateDir, tempDir, answers); + + Task.section('Moving to final location'); + await moveApp(tempDir, appDir, answers.name); + } if (!cmd.skipInstall) { Task.section('Building the app'); @@ -157,10 +185,7 @@ export default async (cmd: Command): Promise => { Task.error(String(error)); Task.log('It seems that something went wrong when creating the app 🤔'); - Task.log('We are going to clean up, and then you can try again.'); - Task.section('Cleanup'); - await cleanUp(tempDir); Task.error('🔥 Failed to create app!'); Task.exit(1); } diff --git a/packages/create-app/src/index.ts b/packages/create-app/src/index.ts index 98a3cee908..1f37be56d2 100644 --- a/packages/create-app/src/index.ts +++ b/packages/create-app/src/index.ts @@ -26,10 +26,14 @@ import { version } from '../package.json'; import createApp from './createApp'; const main = (argv: string[]) => { - program.name('backstage-create-app').version(version); - program - .description('Creates a new app in a new directory') + .name('backstage-create-app') + .version(version) + .description('Creates a new app in a new directory or specified path') + .option( + '--path [directory]', + 'Location to store the app defaulting to a new folder with the app name', + ) .option( '--skip-install', 'Skip the install and builds steps after creating the app', diff --git a/packages/e2e-test/src/commands/run.ts b/packages/e2e-test/src/commands/run.ts index 89a46704c2..b0db715f25 100644 --- a/packages/e2e-test/src/commands/run.ts +++ b/packages/e2e-test/src/commands/run.ts @@ -369,7 +369,7 @@ async function testAppServe(pluginName: string, appDir: string) { successful = true; break; } catch (error) { - if (attempts >= 5) { + if (attempts >= 20) { throw new Error(`App serve test failed, ${error}`); } console.log(`App serve failed, trying again, ${error}`); diff --git a/packages/e2e-test/src/lib/helpers.ts b/packages/e2e-test/src/lib/helpers.ts index f326311f07..5193db08ec 100644 --- a/packages/e2e-test/src/lib/helpers.ts +++ b/packages/e2e-test/src/lib/helpers.ts @@ -25,9 +25,6 @@ import { promisify } from 'util'; const execFile = promisify(execFileCb); -const EXPECTED_LOAD_ERRORS = - /ECONNREFUSED|ECONNRESET|did not get to load all resources/; - export function spawnPiped(cmd: string[], options?: SpawnOptions) { function pipeWithPrefix(stream: NodeJS.WriteStream, prefix = '') { return (data: Buffer) => { @@ -131,16 +128,19 @@ export async function waitForPageWithText( browser: any, path: string, text: string, - { intervalMs = 1000, maxLoadAttempts = 50 } = {}, + { intervalMs = 1000, maxFindAttempts = 50 } = {}, ) { - let loadAttempts = 0; + let findAttempts = 0; for (;;) { try { - const waitTimeMs = intervalMs * (Math.log10(loadAttempts + 1) + 1); + const waitTimeMs = intervalMs * (findAttempts + 1); console.log(`Attempting to load page at ${path}, waiting ${waitTimeMs}`); await new Promise(resolve => setTimeout(resolve, waitTimeMs)); + await browser.visit(path); + await new Promise(resolve => setTimeout(resolve, waitTimeMs)); + const escapedText = text.replace(/"|\\/g, '\\$&'); browser.assert.evaluate( `Array.from(document.querySelectorAll("*")).some(el => el.textContent === "${escapedText}")`, @@ -150,15 +150,12 @@ export async function waitForPageWithText( break; } catch (error) { assertError(error); - if (error.message.match(EXPECTED_LOAD_ERRORS)) { - loadAttempts++; - if (loadAttempts >= maxLoadAttempts) { - throw new Error( - `Failed to load page '${path}', max number of attempts reached`, - ); - } - } else { - throw error; + + findAttempts++; + if (findAttempts >= maxFindAttempts) { + throw new Error( + `Failed to load page '${path}', max number of attempts reached`, + ); } } } diff --git a/packages/errors/CHANGELOG.md b/packages/errors/CHANGELOG.md index 368fa26593..9ea2f47cbb 100644 --- a/packages/errors/CHANGELOG.md +++ b/packages/errors/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/errors +## 0.1.4 + +### Patch Changes + +- a15d028517: More API fixes: mark things public, add docs, fix exports +- 10615525f3: Switch to use the json and observable types from `@backstage/types` +- 8c30ae8902: Add `stringifyError` that is useful for logging e.g. `Something went wrong, ${stringifyError(e)}` + ## 0.1.3 ### Patch Changes diff --git a/packages/errors/api-report.md b/packages/errors/api-report.md index a96132cee7..4984919e6a 100644 --- a/packages/errors/api-report.md +++ b/packages/errors/api-report.md @@ -17,7 +17,6 @@ export class ConflictError extends CustomErrorBase {} // @public export class CustomErrorBase extends Error { constructor(message?: string, cause?: Error | unknown); - // (undocumented) readonly cause?: Error | undefined; } diff --git a/packages/errors/package.json b/packages/errors/package.json index b1f214e5af..fe62bb3bba 100644 --- a/packages/errors/package.json +++ b/packages/errors/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/errors", "description": "Common utilities for error handling within Backstage", - "version": "0.1.3", + "version": "0.1.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -35,7 +35,7 @@ "serialize-error": "^8.0.1" }, "devDependencies": { - "@backstage/cli": "^0.8.0", + "@backstage/cli": "^0.8.1", "@types/jest": "^26.0.7" }, "files": [ diff --git a/packages/errors/src/errors/CustomErrorBase.ts b/packages/errors/src/errors/CustomErrorBase.ts index 17149cd398..786e10ef23 100644 --- a/packages/errors/src/errors/CustomErrorBase.ts +++ b/packages/errors/src/errors/CustomErrorBase.ts @@ -33,6 +33,9 @@ import { isError } from './assertion'; * ``` */ export class CustomErrorBase extends Error { + /** + * An inner error that caused this error to be thrown, if any. + */ readonly cause?: Error | undefined; constructor(message?: string, cause?: Error | unknown) { diff --git a/packages/integration-react/CHANGELOG.md b/packages/integration-react/CHANGELOG.md index cddaf2e792..a2a0d0c368 100644 --- a/packages/integration-react/CHANGELOG.md +++ b/packages/integration-react/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/integration-react +## 0.1.13 + +### Patch Changes + +- 36e2b548cb: Clean up the API exports +- Updated dependencies + - @backstage/config@0.1.11 + - @backstage/theme@0.2.12 + - @backstage/integration@0.6.9 + - @backstage/core-components@0.7.2 + - @backstage/core-plugin-api@0.1.12 + ## 0.1.12 ### Patch Changes diff --git a/packages/integration-react/api-report.md b/packages/integration-react/api-report.md index b7feb6b6a9..2db29631a3 100644 --- a/packages/integration-react/api-report.md +++ b/packages/integration-react/api-report.md @@ -65,7 +65,6 @@ export class ScmAuth implements ScmAuthApi { host?: string; }, ): ScmAuth; - // (undocumented) getCredentials(options: ScmAuthTokenOptions): Promise; isUrlSupported(url: URL): boolean; static merge(...providers: ScmAuth[]): ScmAuthApi; @@ -79,7 +78,7 @@ export interface ScmAuthApi { // @public export const scmAuthApiRef: ApiRef; -// @public (undocumented) +// @public export interface ScmAuthTokenOptions extends AuthRequestOptions { additionalScope?: { repoWrite?: boolean; @@ -87,7 +86,7 @@ export interface ScmAuthTokenOptions extends AuthRequestOptions { url: string; } -// @public (undocumented) +// @public export interface ScmAuthTokenResponse { headers: { [name: string]: string; @@ -95,25 +94,21 @@ export interface ScmAuthTokenResponse { token: string; } -// Warning: (ae-missing-release-tag) "ScmIntegrationIcon" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const ScmIntegrationIcon: ({ - type, -}: { - type?: string | undefined; -}) => JSX.Element; +// @public +export const ScmIntegrationIcon: ( + props: ScmIntegrationIconProps, +) => JSX.Element; -// Warning: (ae-missing-release-tag) "ScmIntegrationsApi" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public +export type ScmIntegrationIconProps = { + type?: string; +}; + +// @public export class ScmIntegrationsApi { - // (undocumented) static fromConfig(config: Config): ScmIntegrationRegistry; } -// Warning: (ae-missing-release-tag) "scmIntegrationsApiRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export const scmIntegrationsApiRef: ApiRef; ``` diff --git a/packages/integration-react/package.json b/packages/integration-react/package.json index b0867c755b..b703203ab2 100644 --- a/packages/integration-react/package.json +++ b/packages/integration-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/integration-react", "description": "Frontend package for managing integrations towards external systems", - "version": "0.1.12", + "version": "0.1.13", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,11 +21,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/config": "^0.1.10", - "@backstage/core-components": "^0.7.1", - "@backstage/core-plugin-api": "^0.1.11", - "@backstage/integration": "^0.6.8", - "@backstage/theme": "^0.2.11", + "@backstage/config": "^0.1.11", + "@backstage/core-components": "^0.7.2", + "@backstage/core-plugin-api": "^0.1.12", + "@backstage/integration": "^0.6.9", + "@backstage/theme": "^0.2.12", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -34,15 +34,15 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.0", + "@backstage/cli": "^0.8.1", "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.19", + "@backstage/test-utils": "^0.1.20", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", "@types/jest": "^26.0.7", "@types/node": "^14.14.32", - "msw": "^0.29.0", + "msw": "^0.35.0", "cross-fetch": "^3.0.6" }, "files": [ diff --git a/packages/integration-react/src/api/ScmAuth.ts b/packages/integration-react/src/api/ScmAuth.ts index c34c4da758..be3216962d 100644 --- a/packages/integration-react/src/api/ScmAuth.ts +++ b/packages/integration-react/src/api/ScmAuth.ts @@ -254,6 +254,9 @@ export class ScmAuth implements ScmAuthApi { return url.host === this.#host; } + /** + * Fetches credentials for the given resource. + */ async getCredentials( options: ScmAuthTokenOptions, ): Promise { diff --git a/packages/integration-react/src/api/ScmAuthApi.ts b/packages/integration-react/src/api/ScmAuthApi.ts index d8fc413620..44b007c4a2 100644 --- a/packages/integration-react/src/api/ScmAuthApi.ts +++ b/packages/integration-react/src/api/ScmAuthApi.ts @@ -20,7 +20,11 @@ import { AuthRequestOptions, } from '@backstage/core-plugin-api'; -/** @public */ +/** + * The options that control a {@link ScmAuthApi.getCredentials} call. + * + * @public + */ export interface ScmAuthTokenOptions extends AuthRequestOptions { /** * The URL of the SCM resource to be accessed. @@ -43,7 +47,11 @@ export interface ScmAuthTokenOptions extends AuthRequestOptions { }; } -/** @public */ +/** + * The response from a {@link ScmAuthApi.getCredentials} call. + * + * @public + */ export interface ScmAuthTokenResponse { /** * An authorization token that can be used to authenticate requests. diff --git a/packages/integration-react/src/api/ScmIntegrationsApi.ts b/packages/integration-react/src/api/ScmIntegrationsApi.ts index 6bf2ba8a6d..06f28a6c4d 100644 --- a/packages/integration-react/src/api/ScmIntegrationsApi.ts +++ b/packages/integration-react/src/api/ScmIntegrationsApi.ts @@ -21,12 +21,27 @@ import { } from '@backstage/integration'; import { ApiRef, createApiRef } from '@backstage/core-plugin-api'; +/** + * Factory class for creating {@link @backstage/integration#ScmIntegrationRegistry} instances. + * + * @public + */ export class ScmIntegrationsApi { + /** + * Instantiates an {@link @backstage/integration#ScmIntegrationRegistry}. + * + * @param config - The root of the config hierarchy. + */ static fromConfig(config: Config): ScmIntegrationRegistry { return ScmIntegrations.fromConfig(config); } } +/** + * The API that holds all configured SCM integrations. + * + * @public + */ export const scmIntegrationsApiRef: ApiRef = createApiRef({ id: 'integration.scmintegrations', diff --git a/packages/integration-react/src/components/ScmIntegrationIcon/ScmIntegrationIcon.tsx b/packages/integration-react/src/components/ScmIntegrationIcon/ScmIntegrationIcon.tsx index 80567d5cc3..dd6ba18690 100644 --- a/packages/integration-react/src/components/ScmIntegrationIcon/ScmIntegrationIcon.tsx +++ b/packages/integration-react/src/components/ScmIntegrationIcon/ScmIntegrationIcon.tsx @@ -17,7 +17,25 @@ import CodeIcon from '@material-ui/icons/Code'; import React from 'react'; import { useApp } from '@backstage/core-plugin-api'; -export const ScmIntegrationIcon = ({ type }: { type?: string }) => { +/** + * Props for {@link ScmIntegrationIcon}. + * + * @public + */ +export type ScmIntegrationIconProps = { + /** + * The integration type, e.g. "github". + */ + type?: string; +}; + +/** + * An icon that represents a certain SCM integration. + * + * @public + */ +export const ScmIntegrationIcon = (props: ScmIntegrationIconProps) => { + const { type } = props; const app = useApp(); const DefaultIcon = CodeIcon; const Icon = type ? app.getSystemIcon(type) ?? DefaultIcon : DefaultIcon; diff --git a/packages/integration-react/src/components/ScmIntegrationIcon/index.ts b/packages/integration-react/src/components/ScmIntegrationIcon/index.ts index 86e60e5b99..a487484d39 100644 --- a/packages/integration-react/src/components/ScmIntegrationIcon/index.ts +++ b/packages/integration-react/src/components/ScmIntegrationIcon/index.ts @@ -15,3 +15,4 @@ */ export { ScmIntegrationIcon } from './ScmIntegrationIcon'; +export type { ScmIntegrationIconProps } from './ScmIntegrationIcon'; diff --git a/packages/integration/CHANGELOG.md b/packages/integration/CHANGELOG.md index 327b9e5fcc..b9c6601e6c 100644 --- a/packages/integration/CHANGELOG.md +++ b/packages/integration/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/integration +## 0.6.9 + +### Patch Changes + +- a15d028517: More API fixes: mark things public, add docs, fix exports +- Updated dependencies + - @backstage/config@0.1.11 + ## 0.6.8 ### Patch Changes diff --git a/packages/integration/api-report.md b/packages/integration/api-report.md index 01f84383fe..4c2258779a 100644 --- a/packages/integration/api-report.md +++ b/packages/integration/api-report.md @@ -6,15 +6,11 @@ import { Config } from '@backstage/config'; import { RestEndpointMethodTypes } from '@octokit/rest'; -// Warning: (ae-missing-release-tag) "AwsS3Integration" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export class AwsS3Integration implements ScmIntegration { constructor(integrationConfig: AwsS3IntegrationConfig); // (undocumented) get config(): AwsS3IntegrationConfig; - // Warning: (ae-forgotten-export) The symbol "ScmIntegrationsFactory" needs to be exported by the entry point index.d.ts - // // (undocumented) static factory: ScmIntegrationsFactory; // (undocumented) @@ -31,8 +27,6 @@ export class AwsS3Integration implements ScmIntegration { get type(): string; } -// Warning: (ae-missing-release-tag) "AwsS3IntegrationConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type AwsS3IntegrationConfig = { host: string; @@ -41,9 +35,7 @@ export type AwsS3IntegrationConfig = { roleArn?: string; }; -// Warning: (ae-missing-release-tag) "AzureIntegration" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export class AzureIntegration implements ScmIntegration { constructor(integrationConfig: AzureIntegrationConfig); // (undocumented) @@ -64,17 +56,13 @@ export class AzureIntegration implements ScmIntegration { get type(): string; } -// Warning: (ae-missing-release-tag) "AzureIntegrationConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type AzureIntegrationConfig = { host: string; token?: string; }; -// Warning: (ae-missing-release-tag) "BitbucketIntegration" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export class BitbucketIntegration implements ScmIntegration { constructor(integrationConfig: BitbucketIntegrationConfig); // (undocumented) @@ -95,8 +83,6 @@ export class BitbucketIntegration implements ScmIntegration { get type(): string; } -// Warning: (ae-missing-release-tag) "BitbucketIntegrationConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type BitbucketIntegrationConfig = { host: string; @@ -106,8 +92,6 @@ export type BitbucketIntegrationConfig = { appPassword?: string; }; -// Warning: (ae-missing-release-tag) "defaultScmResolveUrl" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function defaultScmResolveUrl(options: { url: string; @@ -115,92 +99,44 @@ export function defaultScmResolveUrl(options: { lineNumber?: number; }): string; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "getAzureCommitsUrl" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function getAzureCommitsUrl(url: string): string; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "getAzureDownloadUrl" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function getAzureDownloadUrl(url: string): string; -// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag -// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag -// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag -// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag -// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" -// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" -// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" -// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" -// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag -// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag -// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag -// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag -// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" -// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" -// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" -// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "getAzureFileFetchUrl" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function getAzureFileFetchUrl(url: string): string; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "getAzureRequestOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function getAzureRequestOptions( config: AzureIntegrationConfig, additionalHeaders?: Record, ): RequestInit; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "getBitbucketDefaultBranch" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function getBitbucketDefaultBranch( url: string, config: BitbucketIntegrationConfig, ): Promise; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "getBitbucketDownloadUrl" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function getBitbucketDownloadUrl( url: string, config: BitbucketIntegrationConfig, ): Promise; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "getBitbucketFileFetchUrl" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function getBitbucketFileFetchUrl( url: string, config: BitbucketIntegrationConfig, ): string; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "getBitbucketRequestOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function getBitbucketRequestOptions( config: BitbucketIntegrationConfig, ): RequestInit; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-forgotten-export) The symbol "GithubCredentials" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "getGitHubFileFetchUrl" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function getGitHubFileFetchUrl( url: string, @@ -208,36 +144,34 @@ export function getGitHubFileFetchUrl( credentials: GithubCredentials, ): string; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "getGitHubRequestOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public @deprecated export function getGitHubRequestOptions( config: GitHubIntegrationConfig, credentials: GithubCredentials, ): RequestInit; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "getGitLabFileFetchUrl" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function getGitLabFileFetchUrl( url: string, config: GitLabIntegrationConfig, ): Promise; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "getGitLabRequestOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function getGitLabRequestOptions( config: GitLabIntegrationConfig, ): RequestInit; -// Warning: (ae-missing-release-tag) "GithubAppCredentialsMux" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public +export type GithubAppConfig = { + appId: number; + privateKey: string; + webhookSecret: string; + clientId: string; + clientSecret: string; + allowedInstallationOwners?: string[]; +}; + +// @public export class GithubAppCredentialsMux { constructor(config: GitHubIntegrationConfig); // (undocumented) @@ -248,33 +182,26 @@ export class GithubAppCredentialsMux { getAppToken(owner: string, repo?: string): Promise; } -// Warning: (ae-missing-release-tag) "GithubCredentialsProvider" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public +export type GithubCredentials = { + headers?: { + [name: string]: string; + }; + token?: string; + type: GithubCredentialType; +}; + +// @public export class GithubCredentialsProvider { // (undocumented) static create(config: GitHubIntegrationConfig): GithubCredentialsProvider; - // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen - // Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag - // Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag - // Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" - // Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" - // Warning: (tsdoc-undefined-tag) The TSDoc tag "@type" is not defined in this configuration - // Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag - // Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag - // Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" - // Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" getCredentials(opts: { url: string }): Promise; } -// Warning: (ae-missing-release-tag) "GithubCredentialType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export type GithubCredentialType = 'app' | 'token'; -// Warning: (ae-missing-release-tag) "GitHubIntegration" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export class GitHubIntegration implements ScmIntegration { constructor(integrationConfig: GitHubIntegrationConfig); // (undocumented) @@ -295,8 +222,6 @@ export class GitHubIntegration implements ScmIntegration { get type(): string; } -// Warning: (ae-missing-release-tag) "GitHubIntegrationConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type GitHubIntegrationConfig = { host: string; @@ -306,9 +231,7 @@ export type GitHubIntegrationConfig = { apps?: GithubAppConfig[]; }; -// Warning: (ae-missing-release-tag) "GitLabIntegration" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export class GitLabIntegration implements ScmIntegration { constructor(integrationConfig: GitLabIntegrationConfig); // (undocumented) @@ -329,8 +252,6 @@ export class GitLabIntegration implements ScmIntegration { get type(): string; } -// Warning: (ae-missing-release-tag) "GitLabIntegrationConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type GitLabIntegrationConfig = { host: string; @@ -339,118 +260,90 @@ export type GitLabIntegrationConfig = { baseUrl: string; }; -// Warning: (ae-missing-release-tag) "GoogleGcsIntegrationConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type GoogleGcsIntegrationConfig = { clientEmail?: string; privateKey?: string; }; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "readAwsS3IntegrationConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// +// @public +export interface IntegrationsByType { + // (undocumented) + awsS3: ScmIntegrationsGroup; + // (undocumented) + azure: ScmIntegrationsGroup; + // (undocumented) + bitbucket: ScmIntegrationsGroup; + // (undocumented) + github: ScmIntegrationsGroup; + // (undocumented) + gitlab: ScmIntegrationsGroup; +} + // @public export function readAwsS3IntegrationConfig( config: Config, ): AwsS3IntegrationConfig; -// Warning: (ae-missing-release-tag) "readAwsS3IntegrationConfigs" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export function readAwsS3IntegrationConfigs( configs: Config[], ): AwsS3IntegrationConfig[]; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "readAzureIntegrationConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function readAzureIntegrationConfig( config: Config, ): AzureIntegrationConfig; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "readAzureIntegrationConfigs" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function readAzureIntegrationConfigs( configs: Config[], ): AzureIntegrationConfig[]; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "readBitbucketIntegrationConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function readBitbucketIntegrationConfig( config: Config, ): BitbucketIntegrationConfig; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "readBitbucketIntegrationConfigs" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function readBitbucketIntegrationConfigs( configs: Config[], ): BitbucketIntegrationConfig[]; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "readGitHubIntegrationConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function readGitHubIntegrationConfig( config: Config, ): GitHubIntegrationConfig; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "readGitHubIntegrationConfigs" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function readGitHubIntegrationConfigs( configs: Config[], ): GitHubIntegrationConfig[]; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "readGitLabIntegrationConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function readGitLabIntegrationConfig( config: Config, ): GitLabIntegrationConfig; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "readGitLabIntegrationConfigs" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function readGitLabIntegrationConfigs( configs: Config[], ): GitLabIntegrationConfig[]; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "readGoogleGcsIntegrationConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function readGoogleGcsIntegrationConfig( config: Config, ): GoogleGcsIntegrationConfig; -// Warning: (ae-missing-release-tag) "replaceUrlType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export function replaceGitHubUrlType( url: string, type: 'blob' | 'tree' | 'edit', ): string; -// Warning: (ae-missing-release-tag) "ScmIntegration" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export interface ScmIntegration { - // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen resolveEditUrl(url: string): string; - // Warning: (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters - // Warning: (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters - // Warning: (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters resolveUrl(options: { url: string; base: string; @@ -460,8 +353,6 @@ export interface ScmIntegration { type: string; } -// Warning: (ae-missing-release-tag) "ScmIntegrationRegistry" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export interface ScmIntegrationRegistry extends ScmIntegrationsGroup { @@ -475,11 +366,7 @@ export interface ScmIntegrationRegistry github: ScmIntegrationsGroup; // (undocumented) gitlab: ScmIntegrationsGroup; - // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen resolveEditUrl(url: string): string; - // Warning: (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters - // Warning: (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters - // Warning: (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters resolveUrl(options: { url: string; base: string; @@ -487,11 +374,8 @@ export interface ScmIntegrationRegistry }): string; } -// Warning: (ae-missing-release-tag) "ScmIntegrations" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export class ScmIntegrations implements ScmIntegrationRegistry { - // Warning: (ae-forgotten-export) The symbol "IntegrationsByType" needs to be exported by the entry point index.d.ts constructor(integrationsByType: IntegrationsByType); // (undocumented) get awsS3(): ScmIntegrationsGroup; @@ -521,20 +405,20 @@ export class ScmIntegrations implements ScmIntegrationRegistry { }): string; } -// Warning: (ae-missing-release-tag) "ScmIntegrationsGroup" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// +// @public +export type ScmIntegrationsFactory = (options: { + config: Config; +}) => ScmIntegrationsGroup; + // @public export interface ScmIntegrationsGroup { - // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen byHost(host: string): T | undefined; - // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen byUrl(url: string | URL): T | undefined; list(): T[]; } // Warnings were encountered during analysis: // -// src/github/config.d.ts:41:5 - (ae-forgotten-export) The symbol "GithubAppConfig" needs to be exported by the entry point index.d.ts -// src/gitlab/config.d.ts:27:68 - (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag -// src/gitlab/config.d.ts:27:63 - (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" +// src/gitlab/config.d.ts:29:68 - (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag +// src/gitlab/config.d.ts:29:63 - (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" ``` diff --git a/packages/integration/package.json b/packages/integration/package.json index 5dda924580..bd49ecc419 100644 --- a/packages/integration/package.json +++ b/packages/integration/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/integration", "description": "Helpers for managing integrations towards external systems", - "version": "0.6.8", + "version": "0.6.9", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,7 +30,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/config": "^0.1.10", + "@backstage/config": "^0.1.11", "cross-fetch": "^3.0.6", "git-url-parse": "^11.6.0", "@octokit/rest": "^18.5.3", @@ -39,12 +39,12 @@ "lodash": "^4.17.21" }, "devDependencies": { - "@backstage/cli": "^0.8.0", - "@backstage/config-loader": "^0.7.0", - "@backstage/test-utils": "^0.1.19", + "@backstage/cli": "^0.8.1", + "@backstage/config-loader": "^0.7.1", + "@backstage/test-utils": "^0.1.20", "@types/jest": "^26.0.7", "@types/luxon": "^2.0.4", - "msw": "^0.29.0" + "msw": "^0.35.0" }, "files": [ "dist", diff --git a/packages/integration/src/ScmIntegrations.ts b/packages/integration/src/ScmIntegrations.ts index 983ab7d24b..add9e4e016 100644 --- a/packages/integration/src/ScmIntegrations.ts +++ b/packages/integration/src/ScmIntegrations.ts @@ -24,14 +24,24 @@ import { defaultScmResolveUrl } from './helpers'; import { ScmIntegration, ScmIntegrationsGroup } from './types'; import { ScmIntegrationRegistry } from './registry'; -type IntegrationsByType = { +/** + * The set of supported integrations. + * + * @public + */ +export interface IntegrationsByType { awsS3: ScmIntegrationsGroup; azure: ScmIntegrationsGroup; bitbucket: ScmIntegrationsGroup; github: ScmIntegrationsGroup; gitlab: ScmIntegrationsGroup; -}; +} +/** + * Exposes the set of supported integrations. + * + * @public + */ export class ScmIntegrations implements ScmIntegrationRegistry { private readonly byType: IntegrationsByType; diff --git a/packages/integration/src/awsS3/AwsS3Integration.ts b/packages/integration/src/awsS3/AwsS3Integration.ts index e987b8f7a3..1507ff514c 100644 --- a/packages/integration/src/awsS3/AwsS3Integration.ts +++ b/packages/integration/src/awsS3/AwsS3Integration.ts @@ -18,6 +18,11 @@ import { basicIntegrations, defaultScmResolveUrl } from '../helpers'; import { ScmIntegration, ScmIntegrationsFactory } from '../types'; import { AwsS3IntegrationConfig, readAwsS3IntegrationConfigs } from './config'; +/** + * Integrates with AWS S3 or compatible solutions. + * + * @public + */ export class AwsS3Integration implements ScmIntegration { static factory: ScmIntegrationsFactory = ({ config }) => { const configs = readAwsS3IntegrationConfigs( @@ -42,6 +47,7 @@ export class AwsS3Integration implements ScmIntegration { } constructor(private readonly integrationConfig: AwsS3IntegrationConfig) {} + resolveUrl(options: { url: string; base: string; diff --git a/packages/integration/src/awsS3/config.ts b/packages/integration/src/awsS3/config.ts index 5f9cd46a22..6b5a23c85c 100644 --- a/packages/integration/src/awsS3/config.ts +++ b/packages/integration/src/awsS3/config.ts @@ -21,8 +21,9 @@ const AMAZON_AWS_HOST = 'amazonaws.com'; /** * The configuration parameters for a single AWS S3 provider. + * + * @public */ - export type AwsS3IntegrationConfig = { /** * The host of the target that this matches on, e.g. "amazonaws.com" @@ -50,7 +51,8 @@ export type AwsS3IntegrationConfig = { /** * Reads a single Aws S3 integration config. * - * @param config The config object of a single integration + * @param config - The config object of a single integration + * @public */ export function readAwsS3IntegrationConfig( @@ -70,6 +72,13 @@ export function readAwsS3IntegrationConfig( return { host, accessKeyId, secretAccessKey, roleArn }; } +/** + * Reads a set of AWS S3 integration configs, and inserts some defaults for + * public Amazon AWS if not specified. + * + * @param configs - The config objects of the integrations + * @public + */ export function readAwsS3IntegrationConfigs( configs: Config[], ): AwsS3IntegrationConfig[] { diff --git a/packages/integration/src/azure/AzureIntegration.ts b/packages/integration/src/azure/AzureIntegration.ts index ab1b2489ae..d036d88c21 100644 --- a/packages/integration/src/azure/AzureIntegration.ts +++ b/packages/integration/src/azure/AzureIntegration.ts @@ -19,6 +19,11 @@ import { ScmIntegration, ScmIntegrationsFactory } from '../types'; import { AzureUrl } from './AzureUrl'; import { AzureIntegrationConfig, readAzureIntegrationConfigs } from './config'; +/** + * Microsoft Azure based integration. + * + * @public + */ export class AzureIntegration implements ScmIntegration { static factory: ScmIntegrationsFactory = ({ config }) => { const configs = readAzureIntegrationConfigs( diff --git a/packages/integration/src/azure/config.ts b/packages/integration/src/azure/config.ts index 9755bbbe24..2d722d1589 100644 --- a/packages/integration/src/azure/config.ts +++ b/packages/integration/src/azure/config.ts @@ -21,6 +21,8 @@ const AZURE_HOST = 'dev.azure.com'; /** * The configuration parameters for a single Azure provider. + * + * @public */ export type AzureIntegrationConfig = { /** @@ -41,7 +43,8 @@ export type AzureIntegrationConfig = { /** * Reads a single Azure integration config. * - * @param config The config object of a single integration + * @param config - The config object of a single integration + * @public */ export function readAzureIntegrationConfig( config: Config, @@ -62,7 +65,8 @@ export function readAzureIntegrationConfig( * Reads a set of Azure integration configs, and inserts some defaults for * public Azure if not specified. * - * @param configs All of the integration config objects + * @param configs - All of the integration config objects + * @public */ export function readAzureIntegrationConfigs( configs: Config[], diff --git a/packages/integration/src/azure/core.ts b/packages/integration/src/azure/core.ts index 30603b1f09..7461954267 100644 --- a/packages/integration/src/azure/core.ts +++ b/packages/integration/src/azure/core.ts @@ -21,11 +21,14 @@ import { AzureIntegrationConfig } from './config'; * Given a URL pointing to a file on a provider, returns a URL that is suitable * for fetching the contents of the data. * - * Converts - * from: https://dev.azure.com/{organization}/{project}/_git/reponame?path={path}&version=GB{commitOrBranch}&_a=contents - * to: https://dev.azure.com/{organization}/{project}/_apis/git/repositories/reponame/items?path={path}&version={commitOrBranch} + * @remarks * - * @param url A URL pointing to a file + * Converts + * - from: `https://dev.azure.com/{organization}/{project}/_git/reponame?path={path}&version=GB{commitOrBranch}&_a=contents` + * - to: `https://dev.azure.com/{organization}/{project}/_apis/git/repositories/reponame/items?path={path}&version={commitOrBranch}` + * + * @param url - A URL pointing to a file + * @public */ export function getAzureFileFetchUrl(url: string): string { return AzureUrl.fromRepoUrl(url).toFileUrl(); @@ -35,7 +38,8 @@ export function getAzureFileFetchUrl(url: string): string { * Given a URL pointing to a path on a provider, returns a URL that is suitable * for downloading the subtree. * - * @param url A URL pointing to a path + * @param url - A URL pointing to a path + * @public */ export function getAzureDownloadUrl(url: string): string { return AzureUrl.fromRepoUrl(url).toArchiveUrl(); @@ -44,7 +48,8 @@ export function getAzureDownloadUrl(url: string): string { /** * Given a URL, return the API URL to fetch commits on the branch. * - * @param url A URL pointing to a repository or a sub-path + * @param url - A URL pointing to a repository or a sub-path + * @public */ export function getAzureCommitsUrl(url: string): string { return AzureUrl.fromRepoUrl(url).toCommitsUrl(); @@ -53,7 +58,8 @@ export function getAzureCommitsUrl(url: string): string { /** * Gets the request options necessary to make requests to a given provider. * - * @param config The relevant provider config + * @param config - The relevant provider config + * @public */ export function getAzureRequestOptions( config: AzureIntegrationConfig, diff --git a/packages/integration/src/bitbucket/BitbucketIntegration.ts b/packages/integration/src/bitbucket/BitbucketIntegration.ts index 07c04cd41e..6c21d716b7 100644 --- a/packages/integration/src/bitbucket/BitbucketIntegration.ts +++ b/packages/integration/src/bitbucket/BitbucketIntegration.ts @@ -22,6 +22,11 @@ import { readBitbucketIntegrationConfigs, } from './config'; +/** + * A Bitbucket based integration. + * + * @public + */ export class BitbucketIntegration implements ScmIntegration { static factory: ScmIntegrationsFactory = ({ config, diff --git a/packages/integration/src/bitbucket/config.ts b/packages/integration/src/bitbucket/config.ts index e2758952e9..1cd911aad3 100644 --- a/packages/integration/src/bitbucket/config.ts +++ b/packages/integration/src/bitbucket/config.ts @@ -23,6 +23,8 @@ const BITBUCKET_API_BASE_URL = 'https://api.bitbucket.org/2.0'; /** * The configuration parameters for a single Bitbucket API provider. + * + * @public */ export type BitbucketIntegrationConfig = { /** @@ -66,7 +68,8 @@ export type BitbucketIntegrationConfig = { /** * Reads a single Bitbucket integration config. * - * @param config The config object of a single integration + * @param config - The config object of a single integration + * @public */ export function readBitbucketIntegrationConfig( config: Config, @@ -102,7 +105,8 @@ export function readBitbucketIntegrationConfig( * Reads a set of Bitbucket integration configs, and inserts some defaults for * public Bitbucket if not specified. * - * @param configs All of the integration config objects + * @param configs - All of the integration config objects + * @public */ export function readBitbucketIntegrationConfigs( configs: Config[], diff --git a/packages/integration/src/bitbucket/core.test.ts b/packages/integration/src/bitbucket/core.test.ts index 0de1d5aaab..2b16be82d4 100644 --- a/packages/integration/src/bitbucket/core.test.ts +++ b/packages/integration/src/bitbucket/core.test.ts @@ -16,7 +16,7 @@ import { rest } from 'msw'; import { setupServer } from 'msw/node'; -import { msw } from '@backstage/test-utils'; +import { setupRequestMockHandlers } from '@backstage/test-utils'; import { BitbucketIntegrationConfig } from './config'; import { getBitbucketDefaultBranch, @@ -27,7 +27,7 @@ import { describe('bitbucket core', () => { const worker = setupServer(); - msw.setupDefaultHandlers(worker); + setupRequestMockHandlers(worker); describe('getBitbucketRequestOptions', () => { it('inserts a token when needed', () => { diff --git a/packages/integration/src/bitbucket/core.ts b/packages/integration/src/bitbucket/core.ts index f8f8f56fa8..afcb9fcfdb 100644 --- a/packages/integration/src/bitbucket/core.ts +++ b/packages/integration/src/bitbucket/core.ts @@ -21,8 +21,9 @@ import { BitbucketIntegrationConfig } from './config'; /** * Given a URL pointing to a path on a provider, returns the default branch. * - * @param url A URL pointing to a path - * @param config The relevant provider config + * @param url - A URL pointing to a path + * @param config - The relevant provider config + * @public */ export async function getBitbucketDefaultBranch( url: string, @@ -71,8 +72,9 @@ export async function getBitbucketDefaultBranch( * Given a URL pointing to a path on a provider, returns a URL that is suitable * for downloading the subtree. * - * @param url A URL pointing to a path - * @param config The relevant provider config + * @param url - A URL pointing to a path + * @param config - The relevant provider config + * @public */ export async function getBitbucketDownloadUrl( url: string, @@ -108,12 +110,15 @@ export async function getBitbucketDownloadUrl( * Given a URL pointing to a file on a provider, returns a URL that is suitable * for fetching the contents of the data. * + * @remarks + * * Converts * from: https://bitbucket.org/orgname/reponame/src/master/file.yaml * to: https://api.bitbucket.org/2.0/repositories/orgname/reponame/src/master/file.yaml * - * @param url A URL pointing to a file - * @param config The relevant provider config + * @param url - A URL pointing to a file + * @param config - The relevant provider config + * @public */ export function getBitbucketFileFetchUrl( url: string, @@ -148,7 +153,8 @@ export function getBitbucketFileFetchUrl( /** * Gets the request options necessary to make requests to a given provider. * - * @param config The relevant provider config + * @param config - The relevant provider config + * @public */ export function getBitbucketRequestOptions( config: BitbucketIntegrationConfig, diff --git a/packages/integration/src/github/GitHubIntegration.test.ts b/packages/integration/src/github/GitHubIntegration.test.ts index efc1de782e..ccceb34d88 100644 --- a/packages/integration/src/github/GitHubIntegration.test.ts +++ b/packages/integration/src/github/GitHubIntegration.test.ts @@ -15,7 +15,7 @@ */ import { ConfigReader } from '@backstage/config'; -import { GitHubIntegration, replaceUrlType } from './GitHubIntegration'; +import { GitHubIntegration, replaceGitHubUrlType } from './GitHubIntegration'; describe('GitHubIntegration', () => { it('has a working factory', () => { @@ -80,25 +80,28 @@ describe('GitHubIntegration', () => { }); }); -describe('replaceUrlType', () => { +describe('replaceGitHubUrlType', () => { it('should replace with expected type', () => { expect( - replaceUrlType( + replaceGitHubUrlType( 'https://github.com/backstage/backstage/blob/master/README.md', 'edit', ), ).toBe('https://github.com/backstage/backstage/edit/master/README.md'); expect( - replaceUrlType( + replaceGitHubUrlType( 'https://github.com/webmodules/blob/blob/master/test', 'tree', ), ).toBe('https://github.com/webmodules/blob/tree/master/test'); expect( - replaceUrlType('https://github.com/blob/blob/blob/master/test', 'tree'), + replaceGitHubUrlType( + 'https://github.com/blob/blob/blob/master/test', + 'tree', + ), ).toBe('https://github.com/blob/blob/tree/master/test'); expect( - replaceUrlType( + replaceGitHubUrlType( 'https://github.com/backstage/backstage/edit/tree/README.md', 'blob', ), diff --git a/packages/integration/src/github/GitHubIntegration.ts b/packages/integration/src/github/GitHubIntegration.ts index 3b53fe51e8..1db0b1fae5 100644 --- a/packages/integration/src/github/GitHubIntegration.ts +++ b/packages/integration/src/github/GitHubIntegration.ts @@ -21,6 +21,11 @@ import { readGitHubIntegrationConfigs, } from './config'; +/** + * A GitHub based integration. + * + * @public + */ export class GitHubIntegration implements ScmIntegration { static factory: ScmIntegrationsFactory = ({ config }) => { const configs = readGitHubIntegrationConfigs( @@ -54,15 +59,22 @@ export class GitHubIntegration implements ScmIntegration { // GitHub uses blob URLs for files and tree urls for directory listings. But // there is a redirect from tree to blob for files, so we can always return // tree urls here. - return replaceUrlType(defaultScmResolveUrl(options), 'tree'); + return replaceGitHubUrlType(defaultScmResolveUrl(options), 'tree'); } resolveEditUrl(url: string): string { - return replaceUrlType(url, 'edit'); + return replaceGitHubUrlType(url, 'edit'); } } -export function replaceUrlType( +/** + * Takes a GitHub URL and replaces the type part (blob, tree etc). + * + * @param url - The original URL + * @param type - The desired type, e.g. "blob" + * @public + */ +export function replaceGitHubUrlType( url: string, type: 'blob' | 'tree' | 'edit', ): string { diff --git a/packages/integration/src/github/GithubCredentialsProvider.ts b/packages/integration/src/github/GithubCredentialsProvider.ts index 278a1ed028..ece692fecc 100644 --- a/packages/integration/src/github/GithubCredentialsProvider.ts +++ b/packages/integration/src/github/GithubCredentialsProvider.ts @@ -159,7 +159,11 @@ class GithubAppManager { } } -// GithubAppCredentialsMux corresponds to a Github installation which internally could hold several GitHub Apps. +/** + * Corresponds to a Github installation which internally could hold several GitHub Apps. + * + * @public + */ export class GithubAppCredentialsMux { private readonly apps: GithubAppManager[]; @@ -211,15 +215,32 @@ export class GithubAppCredentialsMux { } } +/** + * The type of credentials produced by the credential provider. + * + * @public + */ export type GithubCredentialType = 'app' | 'token'; +/** + * A set of credentials information for a GitHub integration. + * + * @public + */ export type GithubCredentials = { headers?: { [name: string]: string }; token?: string; type: GithubCredentialType; }; -// TODO: Possibly move this to a backend only package so that it's not used in the frontend by mistake +/** + * Handles the creation and caching of credentials for GitHub integrations. + * + * @public + * @remarks + * + * TODO: Possibly move this to a backend only package so that it's not used in the frontend by mistake + */ export class GithubCredentialsProvider { static create(config: GitHubIntegrationConfig): GithubCredentialsProvider { return new GithubCredentialsProvider( @@ -234,13 +255,24 @@ export class GithubCredentialsProvider { ) {} /** - * Returns GithubCredentials for requested url. - * Consecutive calls to this method with the same url will return cached credentials. + * Returns {@link GithubCredentials} for a given URL. + * + * @remarks + * + * Consecutive calls to this method with the same URL will return cached + * credentials. + * * The shortest lifetime for a token returned is 10 minutes. - * @param opts containing the organization or repository url - * @returns {Promise} of @type {GithubCredentials}. + * * @example - * const { token, headers } = await getCredentials({url: 'github.com/backstage/foobar'}) + * ```ts + * const { token, headers } = await getCredentials({ + * url: 'github.com/backstage/foobar' + * }) + * ``` + * + * @param opts - The organization or repository URL + * @returns A promise of {@link GithubCredentials}. */ async getCredentials(opts: { url: string }): Promise { const parsed = parseGitUrl(opts.url); diff --git a/packages/integration/src/github/config.ts b/packages/integration/src/github/config.ts index 49674681f1..93801e96fb 100644 --- a/packages/integration/src/github/config.ts +++ b/packages/integration/src/github/config.ts @@ -24,6 +24,8 @@ const GITHUB_RAW_BASE_URL = 'https://raw.githubusercontent.com'; /** * The configuration parameters for a single GitHub integration. + * + * @public */ export type GitHubIntegrationConfig = { /** @@ -70,7 +72,12 @@ export type GitHubIntegrationConfig = { /** * The configuration parameters for authenticating a GitHub Application. - * A Github Apps configuration can be generated using the `backstage-cli create-github-app` command. + * + * @remarks + * + * A GitHub Apps configuration can be generated using the `backstage-cli create-github-app` command. + * + * @public */ export type GithubAppConfig = { /** @@ -107,7 +114,8 @@ export type GithubAppConfig = { /** * Reads a single GitHub integration config. * - * @param config The config object of a single integration + * @param config - The config object of a single integration + * @public */ export function readGitHubIntegrationConfig( config: Config, @@ -152,7 +160,8 @@ export function readGitHubIntegrationConfig( * Reads a set of GitHub integration configs, and inserts some defaults for * public GitHub if not specified. * - * @param configs All of the integration config objects + * @param configs - All of the integration config objects + * @public */ export function readGitHubIntegrationConfigs( configs: Config[], diff --git a/packages/integration/src/github/core.ts b/packages/integration/src/github/core.ts index 49695ec5ac..2c5e739a26 100644 --- a/packages/integration/src/github/core.ts +++ b/packages/integration/src/github/core.ts @@ -22,13 +22,16 @@ import { GithubCredentials } from './GithubCredentialsProvider'; * Given a URL pointing to a file on a provider, returns a URL that is suitable * for fetching the contents of the data. * + * @remarks + * * Converts * from: https://github.com/a/b/blob/branchname/path/to/c.yaml * to: https://api.github.com/repos/a/b/contents/path/to/c.yaml?ref=branchname * or: https://raw.githubusercontent.com/a/b/branchname/c.yaml * - * @param url A URL pointing to a file - * @param config The relevant provider config + * @param url - A URL pointing to a file + * @param config - The relevant provider config + * @public */ export function getGitHubFileFetchUrl( url: string, @@ -64,7 +67,8 @@ export function getGitHubFileFetchUrl( * Gets the request options necessary to make requests to a given provider. * * @deprecated This function is no longer used internally - * @param config The relevant provider config + * @param config - The relevant provider config + * @public */ export function getGitHubRequestOptions( config: GitHubIntegrationConfig, diff --git a/packages/integration/src/github/index.ts b/packages/integration/src/github/index.ts index 80d9ce2f26..9c13f13135 100644 --- a/packages/integration/src/github/index.ts +++ b/packages/integration/src/github/index.ts @@ -18,14 +18,14 @@ export { readGitHubIntegrationConfig, readGitHubIntegrationConfigs, } from './config'; -export type { GitHubIntegrationConfig } from './config'; +export type { GithubAppConfig, GitHubIntegrationConfig } from './config'; export { getGitHubFileFetchUrl, getGitHubRequestOptions } from './core'; export { GithubAppCredentialsMux, GithubCredentialsProvider, } from './GithubCredentialsProvider'; -export type { GithubCredentialType } from './GithubCredentialsProvider'; -export { - GitHubIntegration, - replaceUrlType as replaceGitHubUrlType, -} from './GitHubIntegration'; +export type { + GithubCredentials, + GithubCredentialType, +} from './GithubCredentialsProvider'; +export { GitHubIntegration, replaceGitHubUrlType } from './GitHubIntegration'; diff --git a/packages/integration/src/gitlab/GitLabIntegration.ts b/packages/integration/src/gitlab/GitLabIntegration.ts index 70a7c11987..cb24829946 100644 --- a/packages/integration/src/gitlab/GitLabIntegration.ts +++ b/packages/integration/src/gitlab/GitLabIntegration.ts @@ -21,6 +21,11 @@ import { readGitLabIntegrationConfigs, } from './config'; +/** + * A GitLab based integration. + * + * @public + */ export class GitLabIntegration implements ScmIntegration { static factory: ScmIntegrationsFactory = ({ config }) => { const configs = readGitLabIntegrationConfigs( diff --git a/packages/integration/src/gitlab/config.ts b/packages/integration/src/gitlab/config.ts index 7471ba0078..f9c15c3219 100644 --- a/packages/integration/src/gitlab/config.ts +++ b/packages/integration/src/gitlab/config.ts @@ -23,6 +23,8 @@ const GITLAB_API_BASE_URL = 'https://gitlab.com/api/v4'; /** * The configuration parameters for a single GitLab integration. + * + * @public */ export type GitLabIntegrationConfig = { /** @@ -57,7 +59,8 @@ export type GitLabIntegrationConfig = { /** * Reads a single GitLab integration config. * - * @param config The config object of a single integration + * @param config - The config object of a single integration + * @public */ export function readGitLabIntegrationConfig( config: Config, @@ -104,7 +107,8 @@ export function readGitLabIntegrationConfig( * Reads a set of GitLab integration configs, and inserts some defaults for * public GitLab if not specified. * - * @param configs All of the integration config objects + * @param configs - All of the integration config objects + * @public */ export function readGitLabIntegrationConfigs( configs: Config[], diff --git a/packages/integration/src/gitlab/core.ts b/packages/integration/src/gitlab/core.ts index b30d44e2db..e6f4dbc910 100644 --- a/packages/integration/src/gitlab/core.ts +++ b/packages/integration/src/gitlab/core.ts @@ -21,6 +21,8 @@ import fetch from 'cross-fetch'; * Given a URL pointing to a file on a provider, returns a URL that is suitable * for fetching the contents of the data. * + * @remarks + * * Converts * from: https://gitlab.example.com/a/b/blob/master/c.yaml * to: https://gitlab.example.com/a/b/raw/master/c.yaml @@ -28,8 +30,9 @@ import fetch from 'cross-fetch'; * from: https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/filepath * to: https://gitlab.com/api/v4/projects/projectId/repository/files/filepath?ref=branch * - * @param url A URL pointing to a file - * @param config The relevant provider config + * @param url - A URL pointing to a file + * @param config - The relevant provider config + * @public */ export async function getGitLabFileFetchUrl( url: string, @@ -48,7 +51,8 @@ export async function getGitLabFileFetchUrl( /** * Gets the request options necessary to make requests to a given provider. * - * @param config The relevant provider config + * @param config - The relevant provider config + * @public */ export function getGitLabRequestOptions( config: GitLabIntegrationConfig, diff --git a/packages/integration/src/googleGcs/config.ts b/packages/integration/src/googleGcs/config.ts index 0945a0e467..3c03204e4c 100644 --- a/packages/integration/src/googleGcs/config.ts +++ b/packages/integration/src/googleGcs/config.ts @@ -18,6 +18,8 @@ import { Config } from '@backstage/config'; /** * The configuration parameters for a single Google Cloud Storage provider. + * + * @public */ export type GoogleGcsIntegrationConfig = { /** @@ -33,7 +35,8 @@ export type GoogleGcsIntegrationConfig = { /** * Reads a single Google GCS integration config. * - * @param config The config object of a single integration + * @param config - The config object of a single integration + * @public */ export function readGoogleGcsIntegrationConfig( config: Config, diff --git a/packages/integration/src/helpers.ts b/packages/integration/src/helpers.ts index 52d2cf6571..2e5552d55c 100644 --- a/packages/integration/src/helpers.ts +++ b/packages/integration/src/helpers.ts @@ -59,8 +59,10 @@ export function basicIntegrations( } /** - * Default implementation of ScmIntegration.resolveUrl, that only works with - * URL pathname based providers. + * Default implementation of {@link ScmIntegration} `resolveUrl`, that only + * works with URL pathname based providers. + * + * @public */ export function defaultScmResolveUrl(options: { url: string; diff --git a/packages/integration/src/index.ts b/packages/integration/src/index.ts index 3d5f336e8d..2f33b76ab3 100644 --- a/packages/integration/src/index.ts +++ b/packages/integration/src/index.ts @@ -28,5 +28,10 @@ export * from './googleGcs'; export * from './awsS3'; export { defaultScmResolveUrl } from './helpers'; export { ScmIntegrations } from './ScmIntegrations'; -export type { ScmIntegration, ScmIntegrationsGroup } from './types'; +export type { IntegrationsByType } from './ScmIntegrations'; +export type { + ScmIntegration, + ScmIntegrationsFactory, + ScmIntegrationsGroup, +} from './types'; export type { ScmIntegrationRegistry } from './registry'; diff --git a/packages/integration/src/registry.ts b/packages/integration/src/registry.ts index 21ca472ccb..5864695e25 100644 --- a/packages/integration/src/registry.ts +++ b/packages/integration/src/registry.ts @@ -23,6 +23,8 @@ import { GitLabIntegration } from './gitlab/GitLabIntegration'; /** * Holds all registered SCM integrations, of all types. + * + * @public */ export interface ScmIntegrationRegistry extends ScmIntegrationsGroup { @@ -43,14 +45,19 @@ export interface ScmIntegrationRegistry * within the file tree of a certain repo, an absolute path of `/b.yaml` does * not resolve to `https://hostname/b.yaml` but rather to * `/b.yaml` inside the file tree of that same repo. - * - * @param options.url The (absolute or relative) URL or path to resolve - * @param options.base The base URL onto which this resolution happens - * @param options.lineNumber The line number in the target file to link to, starting with 1. Only applicable when linking to files. */ resolveUrl(options: { + /** + * The (absolute or relative) URL or path to resolve. + */ url: string; + /** + * The base URL onto which this resolution happens + */ base: string; + /** + * The line number in the target file to link to, starting with 1. Only applicable when linking to files. + */ lineNumber?: number; }): string; @@ -63,7 +70,7 @@ export interface ScmIntegrationRegistry * If this is not possible, the integration can fall back to a URL to view * the file in the web interface. * - * @param url The absolute URL to the file that should be edited. + * @param url - The absolute URL to the file that should be edited. */ resolveEditUrl(url: string): string; } diff --git a/packages/integration/src/types.ts b/packages/integration/src/types.ts index e66b20f8f8..cb4b78eb7c 100644 --- a/packages/integration/src/types.ts +++ b/packages/integration/src/types.ts @@ -18,6 +18,8 @@ import { Config } from '@backstage/config'; /** * Encapsulates a single SCM integration. + * + * @public */ export interface ScmIntegration { /** @@ -42,14 +44,19 @@ export interface ScmIntegration { * within the file tree of a certain repo, an absolute path of `/b.yaml` does * not resolve to `https://hostname/b.yaml` but rather to * `/b.yaml` inside the file tree of that same repo. - * - * @param options.url The (absolute or relative) URL or path to resolve - * @param options.base The base URL onto which this resolution happens - * @param options.lineNumber The line number in the target file to link to, starting with 1. Only applicable when linking to files. */ resolveUrl(options: { + /** + * The (absolute or relative) URL or path to resolve + */ url: string; + /** + * The base URL onto which this resolution happens + */ base: string; + /** + * The line number in the target file to link to, starting with 1. Only applicable when linking to files. + */ lineNumber?: number; }): string; @@ -62,13 +69,15 @@ export interface ScmIntegration { * If this is not possible, the integration can fall back to a URL to view * the file in the web interface. * - * @param url The absolute URL to the file that should be edited. + * @param url - The absolute URL to the file that should be edited. */ resolveEditUrl(url: string): string; } /** * Encapsulates several integrations, that are all of the same type. + * + * @public */ export interface ScmIntegrationsGroup { /** @@ -79,18 +88,23 @@ export interface ScmIntegrationsGroup { /** * Fetches an integration of this type by URL. * - * @param url A URL that matches a registered integration of this type + * @param url - A URL that matches a registered integration of this type */ byUrl(url: string | URL): T | undefined; /** * Fetches an integration of this type by host name. * - * @param url A host name that matches a registered integration of this type + * @param host - A host name that matches a registered integration of this type */ byHost(host: string): T | undefined; } +/** + * A factory function that creates an integration group based on configuration. + * + * @public + */ export type ScmIntegrationsFactory = (options: { config: Config; }) => ScmIntegrationsGroup; diff --git a/packages/search-common/CHANGELOG.md b/packages/search-common/CHANGELOG.md index 34f956586e..e9f45d522e 100644 --- a/packages/search-common/CHANGELOG.md +++ b/packages/search-common/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/search-common +## 0.2.1 + +### Patch Changes + +- 10615525f3: Switch to use the json and observable types from `@backstage/types` + ## 0.2.0 ### Minor Changes diff --git a/packages/search-common/package.json b/packages/search-common/package.json index fee0fe59dd..e913ef66ff 100644 --- a/packages/search-common/package.json +++ b/packages/search-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/search-common", "description": "Common functionalities for Search, to be shared between various search-enabled plugins", - "version": "0.2.0", + "version": "0.2.1", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -39,7 +39,7 @@ "@backstage/types": "^0.1.1" }, "devDependencies": { - "@backstage/cli": "^0.8.0" + "@backstage/cli": "^0.8.1" }, "jest": { "roots": [ diff --git a/packages/techdocs-common/CHANGELOG.md b/packages/techdocs-common/CHANGELOG.md index fa32a0355e..b540f74549 100644 --- a/packages/techdocs-common/CHANGELOG.md +++ b/packages/techdocs-common/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/techdocs-common +## 0.10.5 + +### Patch Changes + +- d207f6ee9e: Support optional bucketRootPath configuration parameter in S3 and GCS publishers +- Updated dependencies + - @backstage/config@0.1.11 + - @backstage/errors@0.1.4 + - @backstage/integration@0.6.9 + - @backstage/backend-common@0.9.8 + - @backstage/catalog-model@0.9.6 + - @backstage/search-common@0.2.1 + ## 0.10.4 ### Patch Changes diff --git a/packages/techdocs-common/package.json b/packages/techdocs-common/package.json index fc3a9376dc..152b9b04f1 100644 --- a/packages/techdocs-common/package.json +++ b/packages/techdocs-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/techdocs-common", "description": "Common functionalities for TechDocs, to be shared between techdocs-backend plugin and techdocs-cli", - "version": "0.10.4", + "version": "0.10.5", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -38,12 +38,12 @@ "dependencies": { "@azure/identity": "^1.5.0", "@azure/storage-blob": "^12.5.0", - "@backstage/backend-common": "^0.9.7", - "@backstage/catalog-model": "^0.9.5", - "@backstage/config": "^0.1.8", - "@backstage/errors": "^0.1.3", - "@backstage/search-common": "^0.2.0", - "@backstage/integration": "^0.6.7", + "@backstage/backend-common": "^0.9.8", + "@backstage/catalog-model": "^0.9.6", + "@backstage/config": "^0.1.11", + "@backstage/errors": "^0.1.4", + "@backstage/search-common": "^0.2.1", + "@backstage/integration": "^0.6.9", "@google-cloud/storage": "^5.6.0", "@trendyol-js/openstack-swift-sdk": "^0.0.4", "@types/express": "^4.17.6", @@ -60,7 +60,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.8.0", + "@backstage/cli": "^0.8.1", "@types/fs-extra": "^9.0.5", "@types/js-yaml": "^4.0.0", "@types/mime-types": "^2.1.0", diff --git a/packages/techdocs-common/src/stages/publish/awsS3.test.ts b/packages/techdocs-common/src/stages/publish/awsS3.test.ts index 9b74d89dda..1f7afa0855 100644 --- a/packages/techdocs-common/src/stages/publish/awsS3.test.ts +++ b/packages/techdocs-common/src/stages/publish/awsS3.test.ts @@ -334,15 +334,12 @@ describe('AwsS3Publish', () => { name: 'path', }; - const techDocsMetadaFilePath = path.posix.join( - ...Object.values(invalidEntityName), - 'techdocs_metadata.json', - ); - const fails = publisher.fetchTechDocsMetadata(invalidEntityName); await expect(fails).rejects.toMatchObject({ - message: `TechDocs metadata fetch failed; caused by Error: The file ${techDocsMetadaFilePath} does not exist!`, + message: expect.stringMatching( + /TechDocs metadata fetch failed; caused by Error: The file .* does not exist/i, + ), }); }); }); diff --git a/packages/techdocs-common/src/stages/publish/googleStorage.test.ts b/packages/techdocs-common/src/stages/publish/googleStorage.test.ts index d31995ea2e..c085594325 100644 --- a/packages/techdocs-common/src/stages/publish/googleStorage.test.ts +++ b/packages/techdocs-common/src/stages/publish/googleStorage.test.ts @@ -332,15 +332,10 @@ describe('GoogleGCSPublish', () => { name: 'path', }; - const techDocsMetadaFilePath = path.posix.join( - ...Object.values(invalidEntityName), - 'techdocs_metadata.json', - ); - const fails = publisher.fetchTechDocsMetadata(invalidEntityName); await expect(fails).rejects.toMatchObject({ - message: `The file ${techDocsMetadaFilePath} does not exist!`, + message: expect.stringMatching(/The file .* does not exist/i), }); }); }); diff --git a/packages/techdocs-common/src/stages/publish/helpers.ts b/packages/techdocs-common/src/stages/publish/helpers.ts index c23c72af38..bc7ed6b97d 100644 --- a/packages/techdocs-common/src/stages/publish/helpers.ts +++ b/packages/techdocs-common/src/stages/publish/helpers.ts @@ -198,10 +198,12 @@ export const getCloudPathForLocalPath = ( ? relativeFilePathTriplet : lowerCaseEntityTriplet(relativeFilePathTriplet); - const destinationWithRoot = path.join( - ...externalStorageRootPath.split(path.posix.sep), + // Again, the / delimiter is intentional, as it represents remote storage. + const destinationWithRoot = [ + // The extra filter prevents unintended double slashes and prefixes. + ...externalStorageRootPath.split(path.posix.sep).filter(s => s !== ''), destination, - ); + ].join('/'); return destinationWithRoot; // Remote storage file relative path }; diff --git a/packages/test-utils-core/CHANGELOG.md b/packages/test-utils-core/CHANGELOG.md index 24d84eb105..35bdf1b2c6 100644 --- a/packages/test-utils-core/CHANGELOG.md +++ b/packages/test-utils-core/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/test-utils-core +## 0.1.4 + +### Patch Changes + +- bb12aae352: Migrates all utility methods from `test-utils-core` into `test-utils` and delete exports from the old package. + This should have no impact since this package is considered internal and have no usages outside core packages. + + Notable changes are that the testing tool `msw.setupDefaultHandlers()` have been deprecated in favour of `setupRequestMockHandlers()`. + ## 0.1.3 ### Patch Changes diff --git a/packages/test-utils-core/package.json b/packages/test-utils-core/package.json index 8256714560..ebe6decddb 100644 --- a/packages/test-utils-core/package.json +++ b/packages/test-utils-core/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/test-utils-core", "description": "Utilities to test Backstage core", - "version": "0.1.3", + "version": "0.1.4", "private": false, "publishConfig": { "access": "public", diff --git a/packages/test-utils/CHANGELOG.md b/packages/test-utils/CHANGELOG.md index a47be922b7..a1fa9d3b6b 100644 --- a/packages/test-utils/CHANGELOG.md +++ b/packages/test-utils/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/test-utils +## 0.1.20 + +### Patch Changes + +- bb12aae352: Migrates all utility methods from `test-utils-core` into `test-utils` and delete exports from the old package. + This should have no impact since this package is considered internal and have no usages outside core packages. + + Notable changes are that the testing tool `msw.setupDefaultHandlers()` have been deprecated in favour of `setupRequestMockHandlers()`. + +- c5bb1df55d: Bump `msw` to `v0.35.0` to resolve [CVE-2021-32796](https://github.com/advisories/GHSA-5fg8-2547-mr8q). +- 10615525f3: Switch to use the json and observable types from `@backstage/types` +- Updated dependencies + - @backstage/theme@0.2.12 + - @backstage/core-app-api@0.1.19 + - @backstage/core-plugin-api@0.1.12 + ## 0.1.19 ### Patch Changes diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 624fdf28b3..269b7b2d38 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/test-utils", "description": "Utilities to test Backstage plugins and apps.", - "version": "0.1.19", + "version": "0.1.20", "private": false, "publishConfig": { "access": "public", @@ -29,16 +29,15 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-app-api": "^0.1.18", - "@backstage/core-plugin-api": "^0.1.11", - "@backstage/theme": "^0.2.11", + "@backstage/core-app-api": "^0.1.19", + "@backstage/core-plugin-api": "^0.1.12", + "@backstage/theme": "^0.2.12", "@backstage/types": "^0.1.1", "@material-ui/core": "^4.12.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", "@types/react": "*", - "msw": "^0.29.0", "react": "^16.12.0", "react-dom": "^16.12.0", "react-router": "6.0.0-beta.0", @@ -46,7 +45,7 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.8.0", + "@backstage/cli": "^0.8.1", "@types/jest": "^26.0.7", "@types/node": "^14.14.32" }, diff --git a/packages/theme/CHANGELOG.md b/packages/theme/CHANGELOG.md index 97d889f450..8709484c79 100644 --- a/packages/theme/CHANGELOG.md +++ b/packages/theme/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/theme +## 0.2.12 + +### Patch Changes + +- 40cfec8b3f: More theme API cleanup +- a15d028517: More API fixes: mark things public, add docs, fix exports + ## 0.2.11 ### Patch Changes diff --git a/packages/theme/api-report.md b/packages/theme/api-report.md index 05833e5e91..72d7887214 100644 --- a/packages/theme/api-report.md +++ b/packages/theme/api-report.md @@ -9,106 +9,129 @@ import { PaletteOptions } from '@material-ui/core/styles/createPalette'; import { Theme } from '@material-ui/core'; import { ThemeOptions } from '@material-ui/core'; -// Warning: (ae-forgotten-export) The symbol "PaletteAdditions" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "BackstagePalette" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export type BackstagePalette = Palette & PaletteAdditions; +// @public +export type BackstagePalette = Palette & BackstagePaletteAdditions; -// Warning: (ae-missing-release-tag) "BackstagePaletteOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export type BackstagePaletteOptions = PaletteOptions & PaletteAdditions; +// @public +export type BackstagePaletteAdditions = { + status: { + ok: string; + warning: string; + error: string; + pending: string; + running: string; + aborted: string; + }; + border: string; + textContrast: string; + textVerySubtle: string; + textSubtle: string; + highlight: string; + errorBackground: string; + warningBackground: string; + infoBackground: string; + errorText: string; + infoText: string; + warningText: string; + linkHover: string; + link: string; + gold: string; + navigation: { + background: string; + indicator: string; + color: string; + selectedColor: string; + }; + tabbar: { + indicator: string; + }; + bursts: { + fontColor: string; + slackChannelText: string; + backgroundColor: { + default: string; + }; + gradient: { + linear: string; + }; + }; + pinSidebarButton: { + icon: string; + background: string; + }; + banner: { + info: string; + error: string; + text: string; + link: string; + }; +}; -// Warning: (ae-missing-release-tag) "BackstageTheme" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public +export type BackstagePaletteOptions = PaletteOptions & + BackstagePaletteAdditions; + +// @public export interface BackstageTheme extends Theme { // (undocumented) - getPageTheme: ({ themeId }: PageThemeSelector) => PageTheme; + getPageTheme: (selector: PageThemeSelector) => PageTheme; // (undocumented) page: PageTheme; // (undocumented) palette: BackstagePalette; } -// Warning: (ae-missing-release-tag) "BackstageThemeOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export interface BackstageThemeOptions extends ThemeOptions { // (undocumented) - getPageTheme: ({ themeId }: PageThemeSelector) => PageTheme; + getPageTheme: (selector: PageThemeSelector) => PageTheme; // (undocumented) page: PageTheme; // (undocumented) palette: BackstagePaletteOptions; } -// Warning: (ae-missing-release-tag) "colorVariants" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export const colorVariants: Record; -// Warning: (ae-missing-release-tag) "createTheme" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export function createTheme(options: SimpleThemeOptions): BackstageTheme; -// Warning: (ae-missing-release-tag) "createThemeOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export function createThemeOptions( options: SimpleThemeOptions, ): BackstageThemeOptions; -// Warning: (ae-missing-release-tag) "createThemeOverrides" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export function createThemeOverrides(theme: BackstageTheme): Overrides; -// Warning: (ae-missing-release-tag) "darkTheme" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export const darkTheme: BackstageTheme; -// Warning: (ae-missing-release-tag) "genPageTheme" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export function genPageTheme(colors: string[], shape: string): PageTheme; -// Warning: (ae-missing-release-tag) "lightTheme" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export const lightTheme: BackstageTheme; -// Warning: (ae-missing-release-tag) "PageTheme" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export type PageTheme = { colors: string[]; shape: string; backgroundImage: string; }; -// Warning: (ae-missing-release-tag) "pageTheme" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export const pageTheme: Record; -// Warning: (ae-missing-release-tag) "PageThemeSelector" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export type PageThemeSelector = { themeId: string; }; -// Warning: (ae-missing-release-tag) "shapes" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export const shapes: Record; -// Warning: (ae-missing-release-tag) "SimpleThemeOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type SimpleThemeOptions = { palette: BackstagePaletteOptions; diff --git a/packages/theme/package.json b/packages/theme/package.json index 3bc209a782..1acc91de79 100644 --- a/packages/theme/package.json +++ b/packages/theme/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/theme", "description": "material-ui theme for use with Backstage.", - "version": "0.2.11", + "version": "0.2.12", "private": false, "publishConfig": { "access": "public", @@ -31,7 +31,7 @@ "@material-ui/core": "^4.12.2" }, "devDependencies": { - "@backstage/cli": "^0.8.0" + "@backstage/cli": "^0.8.1" }, "files": [ "dist" diff --git a/packages/theme/src/baseTheme.ts b/packages/theme/src/baseTheme.ts index 4a45516a55..da663e3398 100644 --- a/packages/theme/src/baseTheme.ts +++ b/packages/theme/src/baseTheme.ts @@ -17,7 +17,6 @@ import { createTheme as createMuiTheme } from '@material-ui/core/styles'; import { darken, lighten } from '@material-ui/core/styles/colorManipulator'; import { Overrides } from '@material-ui/core/styles/overrides'; - import { BackstageTheme, BackstageThemeOptions, @@ -28,6 +27,11 @@ import { pageTheme as defaultPageThemes } from './pageTheme'; const DEFAULT_FONT_FAMILY = '"Helvetica Neue", Helvetica, Roboto, Arial, sans-serif'; +/** + * A helper for creating theme options. + * + * @public + */ export function createThemeOptions( options: SimpleThemeOptions, ): BackstageThemeOptions { @@ -84,6 +88,11 @@ export function createThemeOptions( }; } +/** + * A helper for creating theme overrides. + * + * @public + */ export function createThemeOverrides(theme: BackstageTheme): Overrides { return { MuiCssBaseline: { @@ -271,8 +280,12 @@ export function createThemeOverrides(theme: BackstageTheme): Overrides { }; } -// Creates a Backstage MUI theme using a palette. -// The theme is created with the common Backstage options and component styles. +/** + * Creates a Backstage MUI theme using a palette. The theme is created with the + * common Backstage options and component styles. + * + * @public + */ export function createTheme(options: SimpleThemeOptions): BackstageTheme { const themeOptions = createThemeOptions(options); const baseTheme = createMuiTheme(themeOptions) as BackstageTheme; diff --git a/packages/theme/src/pageTheme.ts b/packages/theme/src/pageTheme.ts index 5765e13c23..ae81dc8534 100644 --- a/packages/theme/src/pageTheme.ts +++ b/packages/theme/src/pageTheme.ts @@ -15,22 +15,33 @@ */ import { PageTheme } from './types'; -/* - # How to add a shape - 1. Get the svg shape from figma, should be ~1400 wide, ~400 high - and only the white->transparent mask, no colors. - 2. Run it through https://jakearchibald.github.io/svgomg/ - 3. Run that through https://github.com/tigt/mini-svg-data-uri - with something like https://npm.runkit.com/mini-svg-data-uri - 4. Wrap the output in `url("")` - 5. Give it a name and paste it into the `shapes` object below. -*/ +/** + * The default predefined burst shapes. + * + * @public + * @remarks + * + * How to add a shape: + * + * 1. Get the svg shape from figma, should be ~1400 wide, ~400 high + * and only the white-to-transparent mask, no colors. + * 2. Run it through https://jakearchibald.github.io/svgomg/ + * 3. Run that through https://github.com/tigt/mini-svg-data-uri + * with something like https://npm.runkit.com/mini-svg-data-uri + * 4. Wrap the output in `url("")` + * 5. Give it a name and paste it into the `shapes` object below. + */ export const shapes: Record = { wave: `url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='1368' height='400' fill='none'%3e%3cmask id='a' width='1368' height='401' x='0' y='0' maskUnits='userSpaceOnUse'%3e%3cpath fill='url(%23paint0_linear)' d='M437 116C223 116 112 0 112 0h1256v400c-82 0-225-21-282-109-112-175-436-175-649-175z'/%3e%3cpath fill='url(%23paint1_linear)' d='M1368 400V282C891-29 788 40 711 161 608 324 121 372 0 361v39h1368z'/%3e%3cpath fill='url(%23paint2_linear)' d='M1368 244v156H0V94c92-24 198-46 375 0l135 41c176 51 195 109 858 109z'/%3e%3cpath fill='url(%23paint3_linear)' d='M1252 400h116c-14-7-35-14-116-16-663-14-837-128-1013-258l-85-61C98 28 46 8 0 0v400h1252z'/%3e%3c/mask%3e%3cg mask='url(%23a)'%3e%3cpath fill='white' d='M-172-98h1671v601H-172z'/%3e%3c/g%3e%3cdefs%3e%3clinearGradient id='paint0_linear' x1='602' x2='1093.5' y1='-960.5' y2='272' gradientUnits='userSpaceOnUse'%3e%3cstop stop-color='white'/%3e%3cstop offset='1' stop-color='white' stop-opacity='0'/%3e%3c/linearGradient%3e%3clinearGradient id='paint1_linear' x1='482' x2='480' y1='1058.5' y2='70.5' gradientUnits='userSpaceOnUse'%3e%3cstop stop-color='white'/%3e%3cstop offset='1' stop-color='white' stop-opacity='0'/%3e%3c/linearGradient%3e%3clinearGradient id='paint2_linear' x1='424' x2='446.1' y1='-587.5' y2='274.6' gradientUnits='userSpaceOnUse'%3e%3cstop stop-color='white'/%3e%3cstop offset='1' stop-color='white' stop-opacity='0'/%3e%3c/linearGradient%3e%3clinearGradient id='paint3_linear' x1='587' x2='349' y1='-1120.5' y2='341' gradientUnits='userSpaceOnUse'%3e%3cstop stop-color='white'/%3e%3cstop offset='1' stop-color='white' stop-opacity='0'/%3e%3c/linearGradient%3e%3c/defs%3e%3c/svg%3e")`, wave2: `url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='1368' height='400' fill='none'%3e%3cmask id='a' width='1764' height='479' x='-229' y='-6' maskUnits='userSpaceOnUse'%3e%3cpath fill='url(%23paint0_linear)' d='M0 400h1350C1321 336 525 33 179-2c-345-34-395 236-408 402H0z'/%3e%3cpath fill='url(%23paint1_linear)' d='M1378 177v223H0V217s219 75 327 52C436 246 717-35 965 45s254 144 413 132z'/%3e%3cpath fill='url(%23paint2_linear)' d='M26 400l-78-16c-170 205-44-6-137-30l-4-1 4 1 137 30c37-45 89-110 159-201 399-514-45 238 1176-50 275-65 354-39 91 267H26z'/%3e%3c/mask%3e%3cg mask='url(%23a)'%3e%3cpath fill='white' d='M0 0h1368v400H0z'/%3e%3c/g%3e%3cdefs%3e%3clinearGradient id='paint0_linear' x1='431' x2='397.3' y1='-599' y2='372.8' gradientUnits='userSpaceOnUse'%3e%3cstop stop-color='white'/%3e%3cstop offset='1' stop-color='white' stop-opacity='0'/%3e%3c/linearGradient%3e%3clinearGradient id='paint1_linear' x1='236.5' x2='446.6' y1='-586' y2='381.5' gradientUnits='userSpaceOnUse'%3e%3cstop stop-color='white'/%3e%3cstop offset='1' stop-color='white' stop-opacity='0'/%3e%3c/linearGradient%3e%3clinearGradient id='paint2_linear' x1='851.8' x2='640.4' y1='-867.2' y2='363.7' gradientUnits='userSpaceOnUse'%3e%3cstop stop-color='white'/%3e%3cstop offset='1' stop-color='white' stop-opacity='0'/%3e%3c/linearGradient%3e%3c/defs%3e%3c/svg%3e")`, round: `url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='1368' height='400' fill='none'%3e%3cmask id='a' width='2269' height='1408' x='-610' y='-509' maskUnits='userSpaceOnUse'%3e%3ccircle cx='1212.8' cy='74.8' r='317.5' fill='url(%23paint0_linear)' transform='rotate(-52 1213 75)'/%3e%3ccircle cx='737.8' cy='445.8' r='317.5' fill='url(%23paint1_linear)' transform='rotate(-116 738 446)'/%3e%3ccircle cx='601.8' cy='52.8' r='418.6' fill='url(%23paint2_linear)' transform='rotate(-117 602 53)'/%3e%3ccircle cx='999.8' cy='364' r='389.1' fill='url(%23paint3_linear)' transform='rotate(31 1000 364)'/%3e%3cellipse cx='-109.2' cy='263.5' fill='url(%23paint4_linear)' rx='429.2' ry='465.8' transform='rotate(-85 -109 264)'/%3e%3c/mask%3e%3cg mask='url(%23a)'%3e%3cpath fill='white' d='M0 0h1368v400H0z'/%3e%3c/g%3e%3cdefs%3e%3clinearGradient id='paint0_linear' x1='1301.2' x2='161.4' y1='-1879.7' y2='-969.6' gradientUnits='userSpaceOnUse'%3e%3cstop stop-color='white'/%3e%3cstop offset='1' stop-color='white' stop-opacity='0'/%3e%3c/linearGradient%3e%3clinearGradient id='paint1_linear' x1='826.2' x2='-313.6' y1='-1508.7' y2='-598.6' gradientUnits='userSpaceOnUse'%3e%3cstop stop-color='white'/%3e%3cstop offset='1' stop-color='white' stop-opacity='0'/%3e%3c/linearGradient%3e%3clinearGradient id='paint2_linear' x1='718.4' x2='-784.3' y1='-2524' y2='-1324.2' gradientUnits='userSpaceOnUse'%3e%3cstop stop-color='white'/%3e%3cstop offset='1' stop-color='white' stop-opacity='0'/%3e%3c/linearGradient%3e%3clinearGradient id='paint3_linear' x1='1108.2' x2='-288.6' y1='-2031.1' y2='-915.9' gradientUnits='userSpaceOnUse'%3e%3cstop stop-color='white'/%3e%3cstop offset='1' stop-color='white' stop-opacity='0'/%3e%3c/linearGradient%3e%3clinearGradient id='paint4_linear' x1='10.4' x2='-1626.5' y1='-2603.8' y2='-1399.5' gradientUnits='userSpaceOnUse'%3e%3cstop stop-color='white'/%3e%3cstop offset='1' stop-color='white' stop-opacity='0'/%3e%3c/linearGradient%3e%3c/defs%3e%3c/svg%3e")`, }; +/** + * The color range variants that are used in e.g. colorful bursts. + * + * @public + */ export const colorVariants: Record = { darkGrey: ['#171717', '#383838'], marineBlue: ['#006D8F', '#0049A1'], @@ -43,9 +54,15 @@ export const colorVariants: Record = { pinkSea: ['#C8077A', '#C2297D'], }; -// As the background shapes and colors are decorative, we place them onto -// the page as a css background-image instead of an html element of its own. -// Utility to not have to write colors and shapes twice. +/** + * Utility to not have to write colors and shapes twice. + * + * @public + * @remarks + * + * As the background shapes and colors are decorative, we place them onto the + * page as a css background-image instead of an html element of its own. + */ export function genPageTheme(colors: string[], shape: string): PageTheme { const gradientColors = colors.length === 1 ? [colors[0], colors[0]] : colors; const gradient = `linear-gradient(90deg, ${gradientColors.join(', ')})`; @@ -54,6 +71,11 @@ export function genPageTheme(colors: string[], shape: string): PageTheme { return { colors, shape, backgroundImage }; } +/** + * All of the builtin page themes. + * + * @public + */ export const pageTheme: Record = { home: genPageTheme(colorVariants.teal, shapes.wave), documentation: genPageTheme(colorVariants.pinkSea, shapes.wave2), diff --git a/packages/theme/src/themes.ts b/packages/theme/src/themes.ts index d7a4a6d785..3eb1bcc252 100644 --- a/packages/theme/src/themes.ts +++ b/packages/theme/src/themes.ts @@ -18,6 +18,11 @@ import { createTheme } from './baseTheme'; import { pageTheme } from './pageTheme'; import { yellow } from '@material-ui/core/colors'; +/** + * The default Backstage light theme. + * + * @public + */ export const lightTheme = createTheme({ palette: { type: 'light', @@ -83,6 +88,11 @@ export const lightTheme = createTheme({ pageTheme, }); +/** + * The default Backstage dark theme. + * + * @public + */ export const darkTheme = createTheme({ palette: { type: 'dark', diff --git a/packages/theme/src/types.ts b/packages/theme/src/types.ts index 76a1b7eb5c..db3e89fa4b 100644 --- a/packages/theme/src/types.ts +++ b/packages/theme/src/types.ts @@ -20,7 +20,12 @@ import { Palette, } from '@material-ui/core/styles/createPalette'; -type PaletteAdditions = { +/** + * Backstage specific additions to the material-ui palette. + * + * @public + */ +export type BackstagePaletteAdditions = { status: { ok: string; warning: string; @@ -74,27 +79,63 @@ type PaletteAdditions = { }; }; -export type BackstagePalette = Palette & PaletteAdditions; -export type BackstagePaletteOptions = PaletteOptions & PaletteAdditions; +/** + * The full Backstage palette. + * + * @public + */ +export type BackstagePalette = Palette & BackstagePaletteAdditions; +/** + * The full Backstage palette options. + * + * @public + */ +export type BackstagePaletteOptions = PaletteOptions & + BackstagePaletteAdditions; + +/** + * Selector for what page theme to use. + * + * @public + */ export type PageThemeSelector = { themeId: string; }; +/** + * A Backstage theme. + * + * @public + */ export interface BackstageTheme extends Theme { palette: BackstagePalette; page: PageTheme; - getPageTheme: ({ themeId }: PageThemeSelector) => PageTheme; -} - -export interface BackstageThemeOptions extends ThemeOptions { - palette: BackstagePaletteOptions; - page: PageTheme; - getPageTheme: ({ themeId }: PageThemeSelector) => PageTheme; + getPageTheme: (selector: PageThemeSelector) => PageTheme; } /** - * A simpler configuration for creating a new theme that just tweaks some parts of the backstage one. + * Backstage theme options. + * + * @public + * @remarks + * + * This is essentially a partial theme definition made by the user, that then + * gets merged together with defaults and other values to form the final + * {@link BackstageTheme}. + * + */ +export interface BackstageThemeOptions extends ThemeOptions { + palette: BackstagePaletteOptions; + page: PageTheme; + getPageTheme: (selector: PageThemeSelector) => PageTheme; +} + +/** + * A simpler configuration for creating a new theme that just tweaks some parts + * of the backstage one. + * + * @public */ export type SimpleThemeOptions = { palette: BackstagePaletteOptions; @@ -103,6 +144,11 @@ export type SimpleThemeOptions = { fontFamily?: string; }; +/** + * The theme definitions for a given layout page. + * + * @public + */ export type PageTheme = { colors: string[]; shape: string; diff --git a/plugins/allure/package.json b/plugins/allure/package.json index 26a5b4cdeb..63864a7239 100644 --- a/plugins/allure/package.json +++ b/plugins/allure/package.json @@ -23,10 +23,10 @@ }, "dependencies": { "@backstage/catalog-model": "^0.9.5", - "@backstage/core-components": "^0.7.1", - "@backstage/core-plugin-api": "^0.1.11", + "@backstage/core-components": "^0.7.2", + "@backstage/core-plugin-api": "^0.1.12", "@backstage/plugin-catalog-react": "^0.6.1", - "@backstage/theme": "^0.2.11", + "@backstage/theme": "^0.2.12", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -36,17 +36,17 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.0", - "@backstage/core-app-api": "^0.1.18", + "@backstage/cli": "^0.8.1", + "@backstage/core-app-api": "^0.1.19", "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.19", + "@backstage/test-utils": "^0.1.20", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", "@types/jest": "^26.0.7", "@types/node": "^14.14.32", "cross-fetch": "^3.0.6", - "msw": "^0.29.0" + "msw": "^0.35.0" }, "files": [ "dist" diff --git a/plugins/allure/src/components/AllureReportComponent/AllureReportComponent.test.tsx b/plugins/allure/src/components/AllureReportComponent/AllureReportComponent.test.tsx index 19c7796e55..34d12aa032 100644 --- a/plugins/allure/src/components/AllureReportComponent/AllureReportComponent.test.tsx +++ b/plugins/allure/src/components/AllureReportComponent/AllureReportComponent.test.tsx @@ -19,12 +19,15 @@ import { ThemeProvider } from '@material-ui/core'; import { lightTheme } from '@backstage/theme'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; -import { msw, renderInTestApp } from '@backstage/test-utils'; +import { + setupRequestMockHandlers, + renderInTestApp, +} from '@backstage/test-utils'; describe('ExampleComponent', () => { const server = setupServer(); // Enable sane handlers for network requests - msw.setupDefaultHandlers(server); + setupRequestMockHandlers(server); // setup mock response beforeEach(() => { diff --git a/plugins/analytics-module-ga/package.json b/plugins/analytics-module-ga/package.json index 0f9759bf4f..25534e9577 100644 --- a/plugins/analytics-module-ga/package.json +++ b/plugins/analytics-module-ga/package.json @@ -22,9 +22,9 @@ }, "dependencies": { "@backstage/config": "^0.1.5", - "@backstage/core-components": "^0.7.1", - "@backstage/core-plugin-api": "^0.1.11", - "@backstage/theme": "^0.2.11", + "@backstage/core-components": "^0.7.2", + "@backstage/core-plugin-api": "^0.1.12", + "@backstage/theme": "^0.2.12", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -34,17 +34,17 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.0", - "@backstage/core-app-api": "^0.1.18", + "@backstage/cli": "^0.8.1", + "@backstage/core-app-api": "^0.1.19", "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.19", + "@backstage/test-utils": "^0.1.20", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", "@types/jest": "^26.0.7", "@types/node": "^14.14.32", "cross-fetch": "^3.0.6", - "msw": "^0.29.0" + "msw": "^0.35.0" }, "files": [ "dist", diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index 78ce0c7ed6..67045c2043 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -32,11 +32,11 @@ "dependencies": { "@asyncapi/react-component": "^0.23.0", "@backstage/catalog-model": "^0.9.5", - "@backstage/core-components": "^0.7.1", - "@backstage/core-plugin-api": "^0.1.11", + "@backstage/core-components": "^0.7.2", + "@backstage/core-plugin-api": "^0.1.12", "@backstage/plugin-catalog": "^0.7.2", "@backstage/plugin-catalog-react": "^0.6.1", - "@backstage/theme": "^0.2.11", + "@backstage/theme": "^0.2.12", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -49,14 +49,14 @@ "react-router": "6.0.0-beta.0", "react-router-dom": "6.0.0-beta.0", "react-use": "^17.2.4", - "swagger-ui-react": "^4.0.0-rc.3", - "swagger-client": "3.16.1" + "swagger-client": "3.16.1", + "swagger-ui-react": "^4.0.0-rc.3" }, "devDependencies": { - "@backstage/cli": "^0.8.0", - "@backstage/core-app-api": "^0.1.18", + "@backstage/cli": "^0.8.1", + "@backstage/core-app-api": "^0.1.19", "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.19", + "@backstage/test-utils": "^0.1.20", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", @@ -64,7 +64,7 @@ "@types/node": "^14.14.32", "@types/swagger-ui-react": "^3.23.3", "cross-fetch": "^3.0.6", - "msw": "^0.29.0" + "msw": "^0.35.0" }, "files": [ "dist" diff --git a/plugins/app-backend/CHANGELOG.md b/plugins/app-backend/CHANGELOG.md index 1424936280..0658b10ebb 100644 --- a/plugins/app-backend/CHANGELOG.md +++ b/plugins/app-backend/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-app-backend +## 0.3.18 + +### Patch Changes + +- 10615525f3: Switch to use the json and observable types from `@backstage/types` +- Updated dependencies + - @backstage/config@0.1.11 + - @backstage/backend-common@0.9.8 + - @backstage/config-loader@0.7.1 + ## 0.3.17 ### Patch Changes diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index 3483bfa8bd..d989457c79 100644 --- a/plugins/app-backend/package.json +++ b/plugins/app-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-app-backend", "description": "A Backstage backend plugin that serves the Backstage frontend app", - "version": "0.3.17", + "version": "0.3.18", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,9 +30,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.7", - "@backstage/config-loader": "^0.7.0", - "@backstage/config": "^0.1.8", + "@backstage/backend-common": "^0.9.8", + "@backstage/config-loader": "^0.7.1", + "@backstage/config": "^0.1.11", "@backstage/types": "^0.1.1", "@types/express": "^4.17.6", "express": "^4.17.1", @@ -42,10 +42,10 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.8.0", + "@backstage/cli": "^0.8.1", "@backstage/types": "^0.1.1", "@types/supertest": "^2.0.8", - "msw": "^0.29.0", + "msw": "^0.35.0", "supertest": "^6.1.3" }, "files": [ diff --git a/plugins/auth-backend/CHANGELOG.md b/plugins/auth-backend/CHANGELOG.md index f8896c95ba..c1ba2038aa 100644 --- a/plugins/auth-backend/CHANGELOG.md +++ b/plugins/auth-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-auth-backend +## 0.4.6 + +### Patch Changes + +- 3b767f19c9: Allow OAuth state to be encoded by a stateEncoder. +- Updated dependencies + - @backstage/test-utils@0.1.20 + - @backstage/config@0.1.11 + - @backstage/errors@0.1.4 + - @backstage/backend-common@0.9.8 + - @backstage/catalog-model@0.9.6 + ## 0.4.5 ### Patch Changes diff --git a/plugins/auth-backend/api-report.md b/plugins/auth-backend/api-report.md index 572f182082..35c93e9537 100644 --- a/plugins/auth-backend/api-report.md +++ b/plugins/auth-backend/api-report.md @@ -293,6 +293,7 @@ export type GithubProviderOptions = { signIn?: { resolver?: SignInResolver; }; + stateEncoder?: StateEncoder; }; // Warning: (ae-missing-release-tag) "GitlabProviderOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -582,6 +583,12 @@ export type WebMessageResponse = // src/providers/atlassian/provider.d.ts:37:5 - (ae-forgotten-export) The symbol "AuthHandler" needs to be exported by the entry point index.d.ts // src/providers/atlassian/provider.d.ts:42:9 - (ae-forgotten-export) The symbol "SignInResolver" needs to be exported by the entry point index.d.ts // src/providers/aws-alb/provider.d.ts:77:5 - (ae-forgotten-export) The symbol "AwsAlbResult" needs to be exported by the entry point index.d.ts -// src/providers/types.d.ts:99:5 - (ae-forgotten-export) The symbol "AuthProviderConfig" needs to be exported by the entry point index.d.ts -// src/providers/types.d.ts:121:8 - (tsdoc-missing-deprecation-message) The @deprecated block must include a deprecation message, e.g. describing the recommended alternative +// src/providers/github/provider.d.ts:71:58 - (tsdoc-escape-greater-than) The ">" character should be escaped using a backslash to avoid confusion with an HTML tag +// src/providers/github/provider.d.ts:71:90 - (tsdoc-escape-greater-than) The ">" character should be escaped using a backslash to avoid confusion with an HTML tag +// src/providers/github/provider.d.ts:71:89 - (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag +// src/providers/github/provider.d.ts:71:67 - (tsdoc-malformed-html-name) Invalid HTML element: Expecting an HTML name +// src/providers/github/provider.d.ts:71:68 - (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" +// src/providers/github/provider.d.ts:78:5 - (ae-forgotten-export) The symbol "StateEncoder" needs to be exported by the entry point index.d.ts +// src/providers/types.d.ts:100:5 - (ae-forgotten-export) The symbol "AuthProviderConfig" needs to be exported by the entry point index.d.ts +// src/providers/types.d.ts:122:8 - (tsdoc-missing-deprecation-message) The @deprecated block must include a deprecation message, e.g. describing the recommended alternative ``` diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index d593db2aa5..5c9d70ea10 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend", "description": "A Backstage backend plugin that handles authentication", - "version": "0.4.5", + "version": "0.4.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,12 +30,12 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.7", + "@backstage/backend-common": "^0.9.8", "@backstage/catalog-client": "^0.5.0", - "@backstage/catalog-model": "^0.9.5", - "@backstage/config": "^0.1.10", - "@backstage/errors": "^0.1.3", - "@backstage/test-utils": "^0.1.19", + "@backstage/catalog-model": "^0.9.6", + "@backstage/config": "^0.1.11", + "@backstage/errors": "^0.1.4", + "@backstage/test-utils": "^0.1.20", "@google-cloud/firestore": "^4.15.1", "@types/express": "^4.17.6", "@types/passport": "^1.0.3", @@ -73,7 +73,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.8.0", + "@backstage/cli": "^0.8.1", "@types/body-parser": "^1.19.0", "@types/cookie-parser": "^1.4.2", "@types/express-session": "^1.17.2", @@ -84,7 +84,7 @@ "@types/passport-saml": "^1.1.3", "@types/passport-strategy": "^0.2.35", "@types/xml2js": "^0.4.7", - "msw": "^0.29.0" + "msw": "^0.35.0" }, "files": [ "dist", diff --git a/plugins/auth-backend/src/providers/github/provider.test.ts b/plugins/auth-backend/src/providers/github/provider.test.ts index d224e8d723..e418ab22c2 100644 --- a/plugins/auth-backend/src/providers/github/provider.test.ts +++ b/plugins/auth-backend/src/providers/github/provider.test.ts @@ -25,6 +25,7 @@ import { } from './provider'; import * as helpers from '../../lib/passport/PassportStrategyHelper'; import { makeProfileInfo } from '../../lib/passport/PassportStrategyHelper'; +import { OAuthStartRequest, encodeState } from '../../lib/oauth'; const mockFrameHandler = jest.spyOn( helpers, @@ -56,6 +57,9 @@ describe('GithubAuthProvider', () => { authHandler: async ({ fullProfile }) => ({ profile: makeProfileInfo(fullProfile), }), + stateEncoder: async (req: OAuthStartRequest) => ({ + encodedState: encodeState(req.state), + }), callbackUrl: 'mock', clientId: 'mock', clientSecret: 'mock', diff --git a/plugins/auth-backend/src/providers/github/provider.ts b/plugins/auth-backend/src/providers/github/provider.ts index 82d231edfa..c7e82cc5ff 100644 --- a/plugins/auth-backend/src/providers/github/provider.ts +++ b/plugins/auth-backend/src/providers/github/provider.ts @@ -31,6 +31,7 @@ import { AuthProviderFactory, AuthHandler, SignInResolver, + StateEncoder, } from '../types'; import { OAuthAdapter, @@ -66,6 +67,7 @@ export type GithubAuthProviderOptions = OAuthProviderOptions & { authorizationUrl?: string; signInResolver?: SignInResolver; authHandler: AuthHandler; + stateEncoder: StateEncoder; tokenIssuer: TokenIssuer; catalogIdentityClient: CatalogIdentityClient; logger: Logger; @@ -78,10 +80,12 @@ export class GithubAuthProvider implements OAuthHandlers { private readonly tokenIssuer: TokenIssuer; private readonly catalogIdentityClient: CatalogIdentityClient; private readonly logger: Logger; + private readonly stateEncoder: StateEncoder; constructor(options: GithubAuthProviderOptions) { this.signInResolver = options.signInResolver; this.authHandler = options.authHandler; + this.stateEncoder = options.stateEncoder; this.tokenIssuer = options.tokenIssuer; this.catalogIdentityClient = options.catalogIdentityClient; this.logger = options.logger; @@ -109,7 +113,7 @@ export class GithubAuthProvider implements OAuthHandlers { async start(req: OAuthStartRequest): Promise { return await executeRedirectStrategy(req, this._strategy, { scope: req.scope, - state: encodeState(req.state), + state: (await this.stateEncoder(req)).encodedState, }); } @@ -209,6 +213,24 @@ export type GithubProviderOptions = { */ resolver?: SignInResolver; }; + + /** + * The state encoder used to encode the 'state' parameter on the OAuth request. + * + * It should return a string that takes the state params (from the request), url encodes the params + * and finally base64 encodes them. + * + * Providing your own stateEncoder will allow you to add addition parameters to the state field. + * + * It is typed as follows: + * export type StateEncoder = (input: OAuthState) => Promise<{encodedState: string}>; + * + * Note: the stateEncoder must encode a 'nonce' value and an 'env' value. Without this, the OAuth flow will fail + * (These two values will be set by the req.state by default) + * + * For more information, please see the helper module in ../../oauth/helpers #readState + */ + stateEncoder?: StateEncoder; }; export const createGithubProvider = ( @@ -263,6 +285,12 @@ export const createGithubProvider = ( logger, }); + const stateEncoder: StateEncoder = + options?.stateEncoder ?? + (async (req: OAuthStartRequest): Promise<{ encodedState: string }> => { + return { encodedState: encodeState(req.state) }; + }); + const provider = new GithubAuthProvider({ clientId, clientSecret, @@ -274,6 +302,7 @@ export const createGithubProvider = ( authHandler, tokenIssuer, catalogIdentityClient, + stateEncoder, logger, }); diff --git a/plugins/auth-backend/src/providers/oidc/provider.test.ts b/plugins/auth-backend/src/providers/oidc/provider.test.ts index c302c44082..ac5035e9a5 100644 --- a/plugins/auth-backend/src/providers/oidc/provider.test.ts +++ b/plugins/auth-backend/src/providers/oidc/provider.test.ts @@ -15,7 +15,7 @@ */ import { Config, ConfigReader } from '@backstage/config'; -import { msw } from '@backstage/test-utils'; +import { setupRequestMockHandlers } from '@backstage/test-utils'; import express from 'express'; import { Session } from 'express-session'; import { JWK, JWT } from 'jose'; @@ -52,7 +52,7 @@ const clientMetadata = { describe('OidcAuthProvider', () => { const worker = setupServer(); - msw.setupDefaultHandlers(worker); + setupRequestMockHandlers(worker); beforeEach(() => { jest.clearAllMocks(); diff --git a/plugins/auth-backend/src/providers/types.ts b/plugins/auth-backend/src/providers/types.ts index 7f7b841c68..089c82b293 100644 --- a/plugins/auth-backend/src/providers/types.ts +++ b/plugins/auth-backend/src/providers/types.ts @@ -21,6 +21,7 @@ import { Config } from '@backstage/config'; import express from 'express'; import { Logger } from 'winston'; import { TokenIssuer } from '../identity/types'; +import { OAuthStartRequest } from '../lib/oauth/types'; import { CatalogIdentityClient } from '../lib/catalog'; export type AuthProviderConfig = { @@ -223,3 +224,7 @@ export type AuthHandlerResult = { profile: ProfileInfo }; export type AuthHandler = ( input: AuthResult, ) => Promise; + +export type StateEncoder = ( + req: OAuthStartRequest, +) => Promise<{ encodedState: string }>; diff --git a/plugins/azure-devops-backend/CHANGELOG.md b/plugins/azure-devops-backend/CHANGELOG.md index a776aea332..b756e7ce4f 100644 --- a/plugins/azure-devops-backend/CHANGELOG.md +++ b/plugins/azure-devops-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-azure-devops-backend +## 0.1.4 + +### Patch Changes + +- 2eebc9bac3: Added duration (startTime and finishTime) and identity (uniqueName) to the RepoBuild results. Also did a bit of refactoring to help finish up the backend items in issue #7641 +- Updated dependencies + - @backstage/config@0.1.11 + - @backstage/backend-common@0.9.8 + ## 0.1.3 ### Patch Changes diff --git a/plugins/azure-devops-backend/package.json b/plugins/azure-devops-backend/package.json index ec2bc84627..8a468b0cc9 100644 --- a/plugins/azure-devops-backend/package.json +++ b/plugins/azure-devops-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-devops-backend", - "version": "0.1.3", + "version": "0.1.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,8 +20,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.7", - "@backstage/config": "^0.1.9", + "@backstage/backend-common": "^0.9.8", + "@backstage/config": "^0.1.11", "@types/express": "^4.17.6", "azure-devops-node-api": "^11.0.1", "express": "^4.17.1", @@ -30,10 +30,10 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.8.0", + "@backstage/cli": "^0.8.1", "@types/supertest": "^2.0.8", "supertest": "^4.0.2", - "msw": "^0.29.0" + "msw": "^0.35.0" }, "files": [ "dist", diff --git a/plugins/azure-devops/CHANGELOG.md b/plugins/azure-devops/CHANGELOG.md index 3687c2ca6c..71904265dd 100644 --- a/plugins/azure-devops/CHANGELOG.md +++ b/plugins/azure-devops/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-azure-devops +## 0.1.2 + +### Patch Changes + +- 7359623e87: Azure DevOps frontend refactoring items from issue #7641 + + - Remove backend setup documentation and linked to the Azure DevOps backend plugin for these instructions + - Improved documentation to be easier to expand with new features in the future + - Removed Router based on feedback from maintainers + - Added tests for `getBuildResultComponent` and `getBuildStateComponent` from the BuildTable + +- Updated dependencies + - @backstage/theme@0.2.12 + - @backstage/errors@0.1.4 + - @backstage/core-components@0.7.2 + - @backstage/plugin-catalog-react@0.6.2 + - @backstage/catalog-model@0.9.6 + - @backstage/core-plugin-api@0.1.12 + ## 0.1.1 ### Patch Changes diff --git a/plugins/azure-devops/package.json b/plugins/azure-devops/package.json index 38f3216c7b..a071205711 100644 --- a/plugins/azure-devops/package.json +++ b/plugins/azure-devops/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-devops", - "version": "0.1.1", + "version": "0.1.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -27,12 +27,12 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.5", - "@backstage/core-components": "^0.7.1", - "@backstage/core-plugin-api": "^0.1.11", - "@backstage/errors": "^0.1.3", - "@backstage/plugin-catalog-react": "^0.6.1", - "@backstage/theme": "^0.2.11", + "@backstage/catalog-model": "^0.9.6", + "@backstage/core-components": "^0.7.2", + "@backstage/core-plugin-api": "^0.1.12", + "@backstage/errors": "^0.1.4", + "@backstage/plugin-catalog-react": "^0.6.2", + "@backstage/theme": "^0.2.12", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -44,17 +44,17 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.0", - "@backstage/core-app-api": "^0.1.18", + "@backstage/cli": "^0.8.1", + "@backstage/core-app-api": "^0.1.19", "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.19", + "@backstage/test-utils": "^0.1.20", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", "@types/jest": "^26.0.7", "@types/node": "^14.14.32", "cross-fetch": "^3.0.6", - "msw": "^0.29.0" + "msw": "^0.35.0" }, "files": [ "dist" diff --git a/plugins/badges/package.json b/plugins/badges/package.json index 5bc2f3e519..0cc3a06509 100644 --- a/plugins/badges/package.json +++ b/plugins/badges/package.json @@ -28,11 +28,11 @@ }, "dependencies": { "@backstage/catalog-model": "^0.9.5", - "@backstage/core-components": "^0.7.1", - "@backstage/core-plugin-api": "^0.1.11", + "@backstage/core-components": "^0.7.2", + "@backstage/core-plugin-api": "^0.1.12", "@backstage/errors": "^0.1.3", "@backstage/plugin-catalog-react": "^0.6.1", - "@backstage/theme": "^0.2.11", + "@backstage/theme": "^0.2.12", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -42,17 +42,17 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.0", - "@backstage/core-app-api": "^0.1.18", + "@backstage/cli": "^0.8.1", + "@backstage/core-app-api": "^0.1.19", "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.19", + "@backstage/test-utils": "^0.1.20", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", "@types/jest": "^26.0.7", "@types/node": "^14.14.32", "cross-fetch": "^3.0.6", - "msw": "^0.29.0" + "msw": "^0.35.0" }, "files": [ "dist" diff --git a/plugins/bazaar/package.json b/plugins/bazaar/package.json index a5dc9f7b1e..5a98abfc3a 100644 --- a/plugins/bazaar/package.json +++ b/plugins/bazaar/package.json @@ -23,8 +23,8 @@ "dependencies": { "@backstage/catalog-model": "^0.9.5", "@backstage/cli": "^0.8.0", - "@backstage/core-components": "^0.7.1", - "@backstage/core-plugin-api": "^0.1.11", + "@backstage/core-components": "^0.7.2", + "@backstage/core-plugin-api": "^0.1.12", "@backstage/plugin-catalog": "^0.7.2", "@backstage/plugin-catalog-react": "^0.6.1", "@material-ui/core": "^4.12.2", @@ -39,7 +39,7 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.0", + "@backstage/cli": "^0.8.1", "@backstage/dev-utils": "^0.2.12", "@testing-library/jest-dom": "^5.10.1", "cross-fetch": "^3.0.6" diff --git a/plugins/bitrise/package.json b/plugins/bitrise/package.json index 9123188947..c4403830f1 100644 --- a/plugins/bitrise/package.json +++ b/plugins/bitrise/package.json @@ -22,10 +22,10 @@ }, "dependencies": { "@backstage/catalog-model": "^0.9.5", - "@backstage/core-components": "^0.7.1", - "@backstage/core-plugin-api": "^0.1.11", + "@backstage/core-components": "^0.7.2", + "@backstage/core-plugin-api": "^0.1.12", "@backstage/plugin-catalog-react": "^0.6.1", - "@backstage/theme": "^0.2.11", + "@backstage/theme": "^0.2.12", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -39,10 +39,10 @@ "recharts": "^1.8.5" }, "devDependencies": { - "@backstage/cli": "^0.8.0", - "@backstage/core-app-api": "^0.1.18", + "@backstage/cli": "^0.8.1", + "@backstage/core-app-api": "^0.1.19", "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.19", + "@backstage/test-utils": "^0.1.20", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", @@ -50,7 +50,7 @@ "@types/node": "^14.14.32", "@types/recharts": "^1.8.15", "cross-fetch": "^3.0.6", - "msw": "^0.29.0" + "msw": "^0.35.0" }, "files": [ "dist" diff --git a/plugins/bitrise/src/api/bitriseApi.client.test.ts b/plugins/bitrise/src/api/bitriseApi.client.test.ts index dde4e1ef69..a85be2a9cb 100644 --- a/plugins/bitrise/src/api/bitriseApi.client.test.ts +++ b/plugins/bitrise/src/api/bitriseApi.client.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { msw } from '@backstage/test-utils'; +import { setupRequestMockHandlers } from '@backstage/test-utils'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; import { BitriseClientApi } from './bitriseApi.client'; @@ -24,7 +24,7 @@ import { UrlPatternDiscovery } from '@backstage/core-app-api'; const server = setupServer(); describe('BitriseClientApi', () => { - msw.setupDefaultHandlers(server); + setupRequestMockHandlers(server); const mockBaseUrl = 'http://backstage:9191/api/proxy'; const discoveryApi = UrlPatternDiscovery.compile(mockBaseUrl); diff --git a/plugins/bitrise/src/components/BitriseBuildsTableComponent/BitriseBuildsTableComponent.test.tsx b/plugins/bitrise/src/components/BitriseBuildsTableComponent/BitriseBuildsTableComponent.test.tsx index 43e596e8d7..a206e28de6 100644 --- a/plugins/bitrise/src/components/BitriseBuildsTableComponent/BitriseBuildsTableComponent.test.tsx +++ b/plugins/bitrise/src/components/BitriseBuildsTableComponent/BitriseBuildsTableComponent.test.tsx @@ -18,7 +18,10 @@ import React from 'react'; import { bitriseApiRef } from '../../plugin'; import { BitriseClientApi } from '../../api/bitriseApi.client'; import { setupServer } from 'msw/node'; -import { msw, renderInTestApp } from '@backstage/test-utils'; +import { + setupRequestMockHandlers, + renderInTestApp, +} from '@backstage/test-utils'; import { useBitriseBuilds } from '../../hooks/useBitriseBuilds'; import { BitriseBuildsTable } from './BitriseBuildsTableComponent'; import { @@ -34,7 +37,7 @@ jest.mock('../../hooks/useBitriseBuilds', () => ({ const server = setupServer(); describe('BitriseBuildsFetchComponent', () => { - msw.setupDefaultHandlers(server); + setupRequestMockHandlers(server); const mockBaseUrl = 'http://backstage:9191'; const discoveryApi = UrlPatternDiscovery.compile(mockBaseUrl); let apis: ApiRegistry; diff --git a/plugins/catalog-backend-module-ldap/CHANGELOG.md b/plugins/catalog-backend-module-ldap/CHANGELOG.md index 6bac00a7a3..a776f3f329 100644 --- a/plugins/catalog-backend-module-ldap/CHANGELOG.md +++ b/plugins/catalog-backend-module-ldap/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-catalog-backend-module-ldap +## 0.3.6 + +### Patch Changes + +- 10615525f3: Switch to use the json and observable types from `@backstage/types` +- Updated dependencies + - @backstage/plugin-catalog-backend@0.17.2 + - @backstage/config@0.1.11 + - @backstage/errors@0.1.4 + - @backstage/catalog-model@0.9.6 + ## 0.3.5 ### Patch Changes diff --git a/plugins/catalog-backend-module-ldap/package.json b/plugins/catalog-backend-module-ldap/package.json index 51c8780a9d..a8c3b71345 100644 --- a/plugins/catalog-backend-module-ldap/package.json +++ b/plugins/catalog-backend-module-ldap/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-ldap", "description": "A Backstage catalog backend modules that helps integrate towards LDAP", - "version": "0.3.5", + "version": "0.3.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -29,10 +29,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.5", - "@backstage/config": "^0.1.10", - "@backstage/errors": "^0.1.3", - "@backstage/plugin-catalog-backend": "^0.17.1", + "@backstage/catalog-model": "^0.9.6", + "@backstage/config": "^0.1.11", + "@backstage/errors": "^0.1.4", + "@backstage/plugin-catalog-backend": "^0.17.2", "@backstage/types": "^0.1.1", "@types/ldapjs": "^2.2.0", "ldapjs": "^2.2.0", @@ -40,7 +40,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.8.0", + "@backstage/cli": "^0.8.1", "@types/lodash": "^4.14.151" }, "files": [ diff --git a/plugins/catalog-backend-module-msgraph/package.json b/plugins/catalog-backend-module-msgraph/package.json index d0f664f428..68e58d922d 100644 --- a/plugins/catalog-backend-module-msgraph/package.json +++ b/plugins/catalog-backend-module-msgraph/package.json @@ -45,7 +45,7 @@ "@backstage/cli": "^0.8.0", "@backstage/test-utils": "^0.1.19", "@types/lodash": "^4.14.151", - "msw": "^0.29.0" + "msw": "^0.35.0" }, "files": [ "dist", diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.test.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.test.ts index cefa4a52ce..6413a97c15 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.test.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.test.ts @@ -15,7 +15,7 @@ */ import * as msal from '@azure/msal-node'; -import { msw } from '@backstage/test-utils'; +import { setupRequestMockHandlers } from '@backstage/test-utils'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; import { MicrosoftGraphClient } from './client'; @@ -28,7 +28,7 @@ describe('MicrosoftGraphClient', () => { let client: MicrosoftGraphClient; const worker = setupServer(); - msw.setupDefaultHandlers(worker); + setupRequestMockHandlers(worker); beforeEach(() => { confidentialClientApplication.acquireTokenByClientCredential.mockResolvedValue( diff --git a/plugins/catalog-backend/CHANGELOG.md b/plugins/catalog-backend/CHANGELOG.md index b098270431..a6bdc8407d 100644 --- a/plugins/catalog-backend/CHANGELOG.md +++ b/plugins/catalog-backend/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-catalog-backend +## 0.17.2 + +### Patch Changes + +- b9ce1ce2c1: Allow custom LocationAnalyzer in NextCatalogBuilder +- 10615525f3: Switch to use the json and observable types from `@backstage/types` +- Updated dependencies + - @backstage/config@0.1.11 + - @backstage/errors@0.1.4 + - @backstage/integration@0.6.9 + - @backstage/backend-common@0.9.8 + - @backstage/catalog-model@0.9.6 + - @backstage/search-common@0.2.1 + ## 0.17.1 ### Patch Changes diff --git a/plugins/catalog-backend/api-report.md b/plugins/catalog-backend/api-report.md index cbef4c90a1..6d21884c12 100644 --- a/plugins/catalog-backend/api-report.md +++ b/plugins/catalog-backend/api-report.md @@ -1295,6 +1295,7 @@ export class NextCatalogBuilder { setEntityDataParser(parser: CatalogProcessorParser): NextCatalogBuilder; // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen setFieldFormatValidators(validators: Partial): NextCatalogBuilder; + setLocationAnalyzer(locationAnalyzer: LocationAnalyzer): NextCatalogBuilder; // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen setPlaceholderResolver( diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 9a44258958..121dd933f9 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend", "description": "The Backstage backend plugin that provides the Backstage catalog", - "version": "0.17.1", + "version": "0.17.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,13 +30,13 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.7", + "@backstage/backend-common": "^0.9.8", "@backstage/catalog-client": "^0.5.0", - "@backstage/catalog-model": "^0.9.5", - "@backstage/config": "^0.1.10", - "@backstage/errors": "^0.1.3", - "@backstage/integration": "^0.6.8", - "@backstage/search-common": "^0.2.0", + "@backstage/catalog-model": "^0.9.6", + "@backstage/config": "^0.1.11", + "@backstage/errors": "^0.1.4", + "@backstage/integration": "^0.6.9", + "@backstage/search-common": "^0.2.1", "@backstage/types": "^0.1.1", "@octokit/graphql": "^4.5.8", "@types/express": "^4.17.6", @@ -63,8 +63,8 @@ }, "devDependencies": { "@backstage/backend-test-utils": "^0.1.8", - "@backstage/cli": "^0.8.0", - "@backstage/test-utils": "^0.1.19", + "@backstage/cli": "^0.8.1", + "@backstage/test-utils": "^0.1.20", "@types/core-js": "^2.5.4", "@types/git-url-parse": "^9.0.0", "@types/lodash": "^4.14.151", @@ -72,7 +72,7 @@ "@types/uuid": "^8.0.0", "@types/yup": "^0.29.13", "aws-sdk-mock": "^5.2.1", - "msw": "^0.29.0", + "msw": "^0.35.0", "sqlite3": "^5.0.1", "supertest": "^6.1.3", "wait-for-expect": "^3.0.2", diff --git a/plugins/catalog-backend/src/ingestion/processors/UrlReaderProcessor.test.ts b/plugins/catalog-backend/src/ingestion/processors/UrlReaderProcessor.test.ts index a63a001082..b7dc0084f2 100644 --- a/plugins/catalog-backend/src/ingestion/processors/UrlReaderProcessor.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/UrlReaderProcessor.test.ts @@ -20,7 +20,7 @@ import { UrlReaders, } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; -import { msw } from '@backstage/test-utils'; +import { setupRequestMockHandlers } from '@backstage/test-utils'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; import { @@ -39,7 +39,7 @@ describe('UrlReaderProcessor', () => { set: jest.fn(), }; const server = setupServer(); - msw.setupDefaultHandlers(server); + setupRequestMockHandlers(server); beforeEach(() => { jest.resetAllMocks(); diff --git a/plugins/catalog-backend/src/ingestion/processors/github/github.test.ts b/plugins/catalog-backend/src/ingestion/processors/github/github.test.ts index e481355fb4..b38153a193 100644 --- a/plugins/catalog-backend/src/ingestion/processors/github/github.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/github/github.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { msw } from '@backstage/test-utils'; +import { setupRequestMockHandlers } from '@backstage/test-utils'; import { graphql } from '@octokit/graphql'; import { graphql as graphqlMsw } from 'msw'; import { setupServer } from 'msw/node'; @@ -28,7 +28,7 @@ import { describe('github', () => { const server = setupServer(); - msw.setupDefaultHandlers(server); + setupRequestMockHandlers(server); describe('getOrganizationUsers', () => { it('reads members', async () => { diff --git a/plugins/catalog-backend/src/service/NextCatalogBuilder.ts b/plugins/catalog-backend/src/service/NextCatalogBuilder.ts index 60a1668f37..835c1dc700 100644 --- a/plugins/catalog-backend/src/service/NextCatalogBuilder.ts +++ b/plugins/catalog-backend/src/service/NextCatalogBuilder.ts @@ -122,6 +122,7 @@ export class NextCatalogBuilder { minSeconds: 100, maxSeconds: 150, }); + private locationAnalyzer: LocationAnalyzer | undefined = undefined; constructor(env: CatalogEnvironment) { this.env = env; @@ -176,6 +177,14 @@ export class NextCatalogBuilder { return this; } + /** + * Overwrites the default location analyzer. + */ + setLocationAnalyzer(locationAnalyzer: LocationAnalyzer): NextCatalogBuilder { + this.locationAnalyzer = locationAnalyzer; + return this; + } + /** * Sets what policies to use for validation of entities between the pre- * processing and post-processing stages. All such policies must pass for the @@ -338,7 +347,8 @@ export class NextCatalogBuilder { ); const locationsCatalog = new DatabaseLocationsCatalog(db); - const locationAnalyzer = new RepoLocationAnalyzer(logger, integrations); + const locationAnalyzer = + this.locationAnalyzer ?? new RepoLocationAnalyzer(logger, integrations); const locationService = new DefaultLocationService( locationStore, orchestrator, diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index b0dca011ca..d5cacc12a6 100644 --- a/plugins/catalog-graph/package.json +++ b/plugins/catalog-graph/package.json @@ -23,32 +23,32 @@ "dependencies": { "@backstage/catalog-client": "^0.5.0", "@backstage/catalog-model": "^0.9.5", - "@backstage/core-components": "^0.7.1", - "@backstage/core-plugin-api": "^0.1.11", + "@backstage/core-components": "^0.7.2", + "@backstage/core-plugin-api": "^0.1.12", "@backstage/plugin-catalog-react": "^0.6.1", - "@backstage/theme": "^0.2.11", + "@backstage/theme": "^0.2.12", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", "@types/react": "*", + "classnames": "^2.3.1", + "lodash": "^4.17.15", + "p-limit": "^3.1.0", + "qs": "^6.9.4", "react": "^16.13.1", "react-dom": "^16.13.1", - "react-use": "^17.2.4", - "classnames": "^2.3.1", "react-router": "6.0.0-beta.0", - "qs": "^6.9.4", - "lodash": "^4.17.15", - "p-limit": "^3.1.0" + "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.0", + "@backstage/cli": "^0.8.1", + "@backstage/core-app-api": "^0.1.19", "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.19", - "@backstage/core-app-api": "^0.1.18", + "@backstage/test-utils": "^0.1.20", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", - "@testing-library/user-event": "^13.1.8", "@testing-library/react-hooks": "^7.0.2", + "@testing-library/user-event": "^13.1.8", "@types/jest": "^26.0.7" }, "files": [ diff --git a/plugins/catalog-graphql/CHANGELOG.md b/plugins/catalog-graphql/CHANGELOG.md index 6a909c57b7..e123f3b17f 100644 --- a/plugins/catalog-graphql/CHANGELOG.md +++ b/plugins/catalog-graphql/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-catalog-graphql +## 0.2.13 + +### Patch Changes + +- 10615525f3: Switch to use the json and observable types from `@backstage/types` +- Updated dependencies + - @backstage/config@0.1.11 + - @backstage/catalog-model@0.9.6 + ## 0.2.12 ### Patch Changes diff --git a/plugins/catalog-graphql/package.json b/plugins/catalog-graphql/package.json index f5705dcc76..5df4f9ba5c 100644 --- a/plugins/catalog-graphql/package.json +++ b/plugins/catalog-graphql/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-graphql", "description": "An experimental Backstage catalog GraphQL module", - "version": "0.2.12", + "version": "0.2.13", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,8 +31,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.5", - "@backstage/config": "^0.1.8", + "@backstage/catalog-model": "^0.9.6", + "@backstage/config": "^0.1.11", "@backstage/types": "^0.1.1", "@graphql-modules/core": "^0.7.17", "apollo-server": "^2.16.1", @@ -43,13 +43,13 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.8.0", - "@backstage/test-utils": "^0.1.11", + "@backstage/cli": "^0.8.1", + "@backstage/test-utils": "^0.1.20", "@graphql-codegen/cli": "^1.21.3", "@graphql-codegen/typescript": "^1.17.7", "@graphql-codegen/typescript-resolvers": "^1.17.7", "eslint-plugin-graphql": "^4.0.0", - "msw": "^0.29.0" + "msw": "^0.35.0" }, "files": [ "dist" diff --git a/plugins/catalog-graphql/src/graphql/module.test.ts b/plugins/catalog-graphql/src/graphql/module.test.ts index 3d1219df31..3e835b3111 100644 --- a/plugins/catalog-graphql/src/graphql/module.test.ts +++ b/plugins/catalog-graphql/src/graphql/module.test.ts @@ -21,7 +21,7 @@ import { setupServer } from 'msw/node'; import { ConfigReader } from '@backstage/config'; import { ReaderEntity } from '../service/client'; import { createLogger } from 'winston'; -import { msw } from '@backstage/test-utils'; +import { setupRequestMockHandlers } from '@backstage/test-utils'; import { gql } from 'apollo-server'; describe('Catalog Module', () => { @@ -33,7 +33,7 @@ describe('Catalog Module', () => { }, }); - msw.setupDefaultHandlers(worker); + setupRequestMockHandlers(worker); describe('Default Entity', () => { beforeEach(() => { diff --git a/plugins/catalog-graphql/src/service/client.test.ts b/plugins/catalog-graphql/src/service/client.test.ts index f10912dc24..8d674a6814 100644 --- a/plugins/catalog-graphql/src/service/client.test.ts +++ b/plugins/catalog-graphql/src/service/client.test.ts @@ -16,11 +16,11 @@ import { CatalogClient } from './client'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; -import { msw } from '@backstage/test-utils'; +import { setupRequestMockHandlers } from '@backstage/test-utils'; describe('Catalog GraphQL Module', () => { const worker = setupServer(); - msw.setupDefaultHandlers(worker); + setupRequestMockHandlers(worker); const baseUrl = 'http://localhost:1234'; diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index fe453ca45d..0287be8e06 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -33,8 +33,8 @@ "dependencies": { "@backstage/catalog-client": "^0.5.0", "@backstage/catalog-model": "^0.9.5", - "@backstage/core-components": "^0.7.1", - "@backstage/core-plugin-api": "^0.1.11", + "@backstage/core-components": "^0.7.2", + "@backstage/core-plugin-api": "^0.1.12", "@backstage/errors": "^0.1.3", "@backstage/integration": "^0.6.8", "@backstage/integration-react": "^0.1.12", @@ -46,26 +46,26 @@ "@types/react": "*", "git-url-parse": "^11.6.0", "js-base64": "^3.6.0", + "lodash": "^4.17.21", "react": "^16.13.1", "react-dom": "^16.13.1", "react-hook-form": "^7.12.2", "react-router": "6.0.0-beta.0", "react-use": "^17.2.4", - "yaml": "^1.10.0", - "lodash": "^4.17.21" + "yaml": "^1.10.0" }, "devDependencies": { - "@backstage/cli": "^0.8.0", - "@backstage/core-app-api": "^0.1.18", + "@backstage/cli": "^0.8.1", + "@backstage/core-app-api": "^0.1.19", "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.19", + "@backstage/test-utils": "^0.1.20", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", "@testing-library/user-event": "^13.1.8", "@types/jest": "^26.0.7", "cross-fetch": "^3.0.6", - "msw": "^0.29.0" + "msw": "^0.35.0" }, "files": [ "dist" diff --git a/plugins/catalog-import/src/api/CatalogImportClient.test.ts b/plugins/catalog-import/src/api/CatalogImportClient.test.ts index 0ddd92e121..276b6d351c 100644 --- a/plugins/catalog-import/src/api/CatalogImportClient.test.ts +++ b/plugins/catalog-import/src/api/CatalogImportClient.test.ts @@ -50,7 +50,7 @@ import { ConfigReader, UrlPatternDiscovery } from '@backstage/core-app-api'; import { ScmIntegrations } from '@backstage/integration'; import { ScmAuthApi } from '@backstage/integration-react'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; -import { msw } from '@backstage/test-utils'; +import { setupRequestMockHandlers } from '@backstage/test-utils'; import { Octokit } from '@octokit/rest'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; @@ -58,7 +58,7 @@ import { CatalogImportClient } from './CatalogImportClient'; describe('CatalogImportClient', () => { const server = setupServer(); - msw.setupDefaultHandlers(server); + setupRequestMockHandlers(server); const mockBaseUrl = 'http://backstage:9191/api/catalog'; const discoveryApi = UrlPatternDiscovery.compile(mockBaseUrl); diff --git a/plugins/catalog-react/CHANGELOG.md b/plugins/catalog-react/CHANGELOG.md index 26999f9e35..cdb80ceac4 100644 --- a/plugins/catalog-react/CHANGELOG.md +++ b/plugins/catalog-react/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-catalog-react +## 0.6.2 + +### Patch Changes + +- f9cc2509f8: EntityTypePicker can be hidden and have an initial filter value set, similar to EntityKindPicker +- 10615525f3: Switch to use the json and observable types from `@backstage/types` +- Updated dependencies + - @backstage/errors@0.1.4 + - @backstage/integration@0.6.9 + - @backstage/core-components@0.7.2 + - @backstage/catalog-model@0.9.6 + - @backstage/core-app-api@0.1.19 + - @backstage/core-plugin-api@0.1.12 + ## 0.6.1 ### Patch Changes diff --git a/plugins/catalog-react/api-report.md b/plugins/catalog-react/api-report.md index 06dccf4b7f..bf8295a8b5 100644 --- a/plugins/catalog-react/api-report.md +++ b/plugins/catalog-react/api-report.md @@ -658,10 +658,20 @@ export class EntityTypeFilter implements EntityFilter { readonly value: string | string[]; } +// Warning: (ae-missing-release-tag) "EntityTypeFilterProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type EntityTypeFilterProps = { + initialFilter?: string; + hidden?: boolean; +}; + // Warning: (ae-missing-release-tag) "EntityTypePicker" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const EntityTypePicker: () => JSX.Element | null; +export const EntityTypePicker: ( + props: EntityTypeFilterProps, +) => JSX.Element | null; // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen // Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index 404ba6893f..40c0d9c739 100644 --- a/plugins/catalog-react/package.json +++ b/plugins/catalog-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-react", "description": "A frontend library that helps other Backstage plugins interact with the catalog", - "version": "0.6.1", + "version": "0.6.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,12 +30,12 @@ }, "dependencies": { "@backstage/catalog-client": "^0.5.0", - "@backstage/catalog-model": "^0.9.5", - "@backstage/core-app-api": "^0.1.18", - "@backstage/core-components": "^0.7.1", - "@backstage/core-plugin-api": "^0.1.11", - "@backstage/errors": "^0.1.3", - "@backstage/integration": "^0.6.8", + "@backstage/catalog-model": "^0.9.6", + "@backstage/core-app-api": "^0.1.19", + "@backstage/core-components": "^0.7.2", + "@backstage/core-plugin-api": "^0.1.12", + "@backstage/errors": "^0.1.4", + "@backstage/integration": "^0.6.9", "@backstage/types": "^0.1.1", "@backstage/version-bridge": "^0.1.0", "@material-ui/core": "^4.12.2", @@ -51,8 +51,8 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.8.0", - "@backstage/test-utils": "^0.1.19", + "@backstage/cli": "^0.8.1", + "@backstage/test-utils": "^0.1.20", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.test.tsx b/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.test.tsx index 9912f3d371..8eba11aeca 100644 --- a/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.test.tsx +++ b/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.test.tsx @@ -121,4 +121,26 @@ describe('', () => { expect(updateFilters).toHaveBeenLastCalledWith({ type: undefined }); }); + + it('respects the query parameter filter value', async () => { + const updateFilters = jest.fn(); + const queryParameters = { type: 'tool' }; + await renderWithEffects( + + + + , + , + ); + + expect(updateFilters).toHaveBeenLastCalledWith({ + type: new EntityTypeFilter(['tool']), + }); + }); }); diff --git a/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.tsx b/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.tsx index bc30bf5b17..225193dc93 100644 --- a/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.tsx +++ b/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.tsx @@ -22,7 +22,13 @@ import { useEntityTypeFilter } from '../../hooks/useEntityTypeFilter'; import { alertApiRef, useApi } from '@backstage/core-plugin-api'; import { Select } from '@backstage/core-components'; -export const EntityTypePicker = () => { +export type EntityTypeFilterProps = { + initialFilter?: string; + hidden?: boolean; +}; + +export const EntityTypePicker = (props: EntityTypeFilterProps) => { + const { hidden, initialFilter } = props; const alertApi = useApi(alertApiRef); const { error, availableTypes, selectedTypes, setSelectedTypes } = useEntityTypeFilter(); @@ -34,7 +40,10 @@ export const EntityTypePicker = () => { severity: 'error', }); } - }, [error, alertApi]); + if (initialFilter) { + setSelectedTypes([initialFilter]); + } + }, [error, alertApi, initialFilter, setSelectedTypes]); if (availableTypes.length === 0 || error) return null; @@ -46,7 +55,7 @@ export const EntityTypePicker = () => { })), ]; - return ( + return hidden ? null : (