diff --git a/packages/backend-app-api/api-report.md b/packages/backend-app-api/api-report.md index 071fd6c1d3..724d3409bf 100644 --- a/packages/backend-app-api/api-report.md +++ b/packages/backend-app-api/api-report.md @@ -204,10 +204,17 @@ export const loggerServiceFactory: () => ServiceFactory< 'plugin' >; -// Warning: (ae-forgotten-export) The symbol "MiddlewareFactory_2" needs to be exported by the entry point index.d.ts -// // @public @deprecated (undocumented) -export const MiddlewareFactory: typeof MiddlewareFactory_2; +export class MiddlewareFactory { + compression(): RequestHandler; + cors(): RequestHandler; + // Warning: (ae-forgotten-export) The symbol "MiddlewareFactory_2" needs to be exported by the entry point index.d.ts + static create(options: MiddlewareFactoryOptions): MiddlewareFactory_2; + error(options?: MiddlewareFactoryErrorOptions): ErrorRequestHandler; + helmet(): RequestHandler; + logging(): RequestHandler; + notFound(): RequestHandler; +} // Warning: (ae-forgotten-export) The symbol "MiddlewareFactoryErrorOptions_2" needs to be exported by the entry point index.d.ts // diff --git a/packages/backend-app-api/src/http/index.ts b/packages/backend-app-api/src/http/index.ts index ab1d134688..8fd1b31e75 100644 --- a/packages/backend-app-api/src/http/index.ts +++ b/packages/backend-app-api/src/http/index.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import { ErrorRequestHandler, RequestHandler } from 'express'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports import { readHttpServerOptions as _readHttpServerOptions, @@ -52,7 +53,113 @@ export const readHelmetOptions = _readHelmetOptions; * @public * @deprecated Please import from `@backstage/backend-defaults/rootHttpRouter` instead. */ -export const MiddlewareFactory = _MiddlewareFactory; +export class MiddlewareFactory { + /** + * Creates a new {@link MiddlewareFactory}. + */ + static create(options: MiddlewareFactoryOptions) { + return _MiddlewareFactory.create(options); + } + + private constructor(private readonly impl: _MiddlewareFactory) {} + + /** + * Returns a middleware that unconditionally produces a 404 error response. + * + * @remarks + * + * Typically you want to place this middleware at the end of the chain, such + * that it's the last one attempted after no other routes matched. + * + * @returns An Express request handler + */ + notFound(): RequestHandler { + return this.impl.notFound(); + } + + /** + * Returns the compression middleware. + * + * @remarks + * + * The middleware will attempt to compress response bodies for all requests + * that traverse through the middleware. + */ + compression(): RequestHandler { + return this.impl.compression(); + } + + /** + * Returns a request logging middleware. + * + * @remarks + * + * Typically you want to place this middleware at the start of the chain, such + * that it always logs requests whether they are "caught" by handlers farther + * down or not. + * + * @returns An Express request handler + */ + logging(): RequestHandler { + return this.impl.logging(); + } + + /** + * Returns a middleware that implements the helmet library. + * + * @remarks + * + * This middleware applies security policies to incoming requests and outgoing + * responses. It is configured using config keys such as `backend.csp`. + * + * @see {@link https://helmetjs.github.io/} + * + * @returns An Express request handler + */ + helmet(): RequestHandler { + return this.impl.helmet(); + } + + /** + * Returns a middleware that implements the cors library. + * + * @remarks + * + * This middleware handles CORS. It is configured using the config key + * `backend.cors`. + * + * @see {@link https://github.com/expressjs/cors} + * + * @returns An Express request handler + */ + cors(): RequestHandler { + return this.impl.cors(); + } + + /** + * Express middleware to handle errors during request processing. + * + * @remarks + * + * This is commonly the very last middleware in the chain. + * + * Its primary purpose is not to do translation of business logic exceptions, + * but rather to be a global catch-all for uncaught "fatal" errors that are + * expected to result in a 500 error. However, it also does handle some common + * error types (such as http-error exceptions, and the well-known error types + * in the `@backstage/errors` package) and returns the enclosed status code + * accordingly. + * + * It will also produce a response body with a serialized form of the error, + * unless a previous handler already did send a body. See + * {@link @backstage/errors#ErrorResponseBody} for the response shape used. + * + * @returns An Express error request handler + */ + error(options: MiddlewareFactoryErrorOptions = {}): ErrorRequestHandler { + return this.impl.error(options); + } +} /** * @public * @deprecated Please import from `@backstage/backend-defaults/rootHttpRouter` instead. diff --git a/packages/backend-common/api-report.md b/packages/backend-common/api-report.md index 7915503d7c..de00ef6a5a 100644 --- a/packages/backend-common/api-report.md +++ b/packages/backend-common/api-report.md @@ -88,27 +88,27 @@ export type AuthCallbackOptions = { // Warning: (ae-forgotten-export) The symbol "AwsS3UrlReader_2" needs to be exported by the entry point index.d.ts // // @public @deprecated (undocumented) -export const AwsS3UrlReader: typeof AwsS3UrlReader_2; +export class AwsS3UrlReader extends AwsS3UrlReader_2 {} // Warning: (ae-forgotten-export) The symbol "AzureUrlReader_2" needs to be exported by the entry point index.d.ts // // @public @deprecated (undocumented) -export const AzureUrlReader: typeof AzureUrlReader_2; +export class AzureUrlReader extends AzureUrlReader_2 {} // Warning: (ae-forgotten-export) The symbol "BitbucketCloudUrlReader_2" needs to be exported by the entry point index.d.ts // // @public @deprecated (undocumented) -export const BitbucketCloudUrlReader: typeof BitbucketCloudUrlReader_2; +export class BitbucketCloudUrlReader extends BitbucketCloudUrlReader_2 {} // Warning: (ae-forgotten-export) The symbol "BitbucketServerUrlReader_2" needs to be exported by the entry point index.d.ts // // @public @deprecated (undocumented) -export const BitbucketServerUrlReader: typeof BitbucketServerUrlReader_2; +export class BitbucketServerUrlReader extends BitbucketServerUrlReader_2 {} // Warning: (ae-forgotten-export) The symbol "BitbucketUrlReader_2" needs to be exported by the entry point index.d.ts // // @public @deprecated (undocumented) -export const BitbucketUrlReader: typeof BitbucketUrlReader_2; +export class BitbucketUrlReader extends BitbucketUrlReader_2 {} // @public @deprecated (undocumented) export type CacheClient = CacheService; @@ -122,7 +122,7 @@ export type CacheClientSetOptions = CacheServiceSetOptions; // Warning: (ae-forgotten-export) The symbol "CacheManager_2" needs to be exported by the entry point index.d.ts // // @public @deprecated (undocumented) -export const CacheManager: typeof CacheManager_2; +export class CacheManager extends CacheManager_2 {} // Warning: (ae-forgotten-export) The symbol "CacheManagerOptions_2" needs to be exported by the entry point index.d.ts // @@ -242,7 +242,7 @@ export type ErrorHandlerOptions = { // Warning: (ae-forgotten-export) The symbol "FetchUrlReader_2" needs to be exported by the entry point index.d.ts // // @public @deprecated (undocumented) -export const FetchUrlReader: typeof FetchUrlReader_2; +export class FetchUrlReader extends FetchUrlReader_2 {} // Warning: (ae-forgotten-export) The symbol "FromReadableArrayOptions_2" needs to be exported by the entry point index.d.ts // @@ -252,7 +252,7 @@ export type FromReadableArrayOptions = FromReadableArrayOptions_2; // Warning: (ae-forgotten-export) The symbol "GerritUrlReader_2" needs to be exported by the entry point index.d.ts // // @public @deprecated (undocumented) -export const GerritUrlReader: typeof GerritUrlReader_2; +export class GerritUrlReader extends GerritUrlReader_2 {} // @public @deprecated export function getRootLogger(): winston.Logger; @@ -339,27 +339,38 @@ export class Git { // Warning: (ae-forgotten-export) The symbol "GiteaUrlReader_2" needs to be exported by the entry point index.d.ts // // @public @deprecated (undocumented) -export const GiteaUrlReader: typeof GiteaUrlReader_2; +export class GiteaUrlReader extends GiteaUrlReader_2 {} // Warning: (ae-forgotten-export) The symbol "GithubUrlReader_2" needs to be exported by the entry point index.d.ts // // @public @deprecated (undocumented) -export const GithubUrlReader: typeof GithubUrlReader_2; +export class GithubUrlReader extends GithubUrlReader_2 {} // Warning: (ae-forgotten-export) The symbol "GitlabUrlReader_2" needs to be exported by the entry point index.d.ts // // @public @deprecated (undocumented) -export const GitlabUrlReader: typeof GitlabUrlReader_2; +export class GitlabUrlReader extends GitlabUrlReader_2 {} // Warning: (ae-forgotten-export) The symbol "HarnessUrlReader_2" needs to be exported by the entry point index.d.ts // // @public @deprecated (undocumented) -export const HarnessUrlReader: typeof HarnessUrlReader_2; +export class HarnessUrlReader extends HarnessUrlReader_2 {} -// Warning: (ae-forgotten-export) The symbol "HostDiscovery_2" needs to be exported by the entry point index.d.ts -// // @public @deprecated -export const HostDiscovery: typeof HostDiscovery_2; +class HostDiscovery implements DiscoveryService { + static fromConfig( + config: Config, + options?: { + basePath?: string; + }, + ): HostDiscovery; + // (undocumented) + getBaseUrl(pluginId: string): Promise; + // (undocumented) + getExternalBaseUrl(pluginId: string): Promise; +} +export { HostDiscovery }; +export { HostDiscovery as SingleHostDiscovery }; // @public @deprecated (undocumented) export const isChildPath: typeof isChildPath_2; @@ -525,7 +536,7 @@ export type ReadUrlResponse = ReadUrlResponse_2; // Warning: (ae-forgotten-export) The symbol "ReadUrlResponseFactory_2" needs to be exported by the entry point index.d.ts // // @public @deprecated (undocumented) -export const ReadUrlResponseFactory: typeof ReadUrlResponseFactory_2; +export class ReadUrlResponseFactory extends ReadUrlResponseFactory_2 {} // Warning: (ae-forgotten-export) The symbol "ReadUrlResponseFactoryFromStreamOptions_2" needs to be exported by the entry point index.d.ts // @@ -626,9 +637,6 @@ export type ServiceBuilder = { // @public @deprecated export function setRootLogger(newLogger: winston.Logger): void; -// @public @deprecated -export const SingleHostDiscovery: typeof HostDiscovery_2; - // @public @deprecated export type StaticAuthOptions = { username?: string; @@ -664,7 +672,7 @@ export type UrlReaderPredicateTuple = UrlReaderPredicateTuple_2; // Warning: (ae-forgotten-export) The symbol "UrlReaders_2" needs to be exported by the entry point index.d.ts // // @public @deprecated (undocumented) -export const UrlReaders: typeof UrlReaders_2; +export class UrlReaders extends UrlReaders_2 {} // Warning: (ae-forgotten-export) The symbol "UrlReadersOptions_2" needs to be exported by the entry point index.d.ts // diff --git a/packages/backend-common/src/deprecated/index.ts b/packages/backend-common/src/deprecated/index.ts index ba8b8e7db2..e3e4101d25 100644 --- a/packages/backend-common/src/deprecated/index.ts +++ b/packages/backend-common/src/deprecated/index.ts @@ -77,8 +77,6 @@ import type { import { DiscoveryService, - LifecycleService, - PluginMetadataService, CacheService, CacheServiceOptions, CacheServiceSetOptions, @@ -97,6 +95,8 @@ import { SearchResponse as _SearchResponse, SearchResponseFile as _SearchResponseFile, UrlReaderService as _UrlReaderService, + LifecycleService, + PluginMetadataService, } from '@backstage/backend-plugin-api'; export * from './hot'; @@ -125,7 +125,45 @@ export type PluginEndpointDiscovery = DiscoveryService; * @public * @deprecated Please import from `@backstage/backend-defaults/discovery` instead. */ -export const HostDiscovery = _HostDiscovery; +export class HostDiscovery implements DiscoveryService { + /** + * Creates a new HostDiscovery discovery instance by reading + * from the `backend` config section, specifically the `.baseUrl` for + * discovering the external URL, and the `.listen` and `.https` config + * for the internal one. + * + * Can be overridden in config by providing a target and corresponding plugins in `discovery.endpoints`. + * eg. + * ```yaml + * discovery: + * endpoints: + * - target: https://internal.example.com/internal-catalog + * plugins: [catalog] + * - target: https://internal.example.com/secure/api/{{pluginId}} + * plugins: [auth, permission] + * - target: + * internal: https://internal.example.com/search + * external: https://example.com/search + * plugins: [search] + * ``` + * + * The basePath defaults to `/api`, meaning the default full internal + * path for the `catalog` plugin will be `http://localhost:7007/api/catalog`. + */ + static fromConfig(config: Config, options?: { basePath?: string }) { + return new HostDiscovery(_HostDiscovery.fromConfig(config, options)); + } + + private constructor(private readonly impl: _HostDiscovery) {} + + async getBaseUrl(pluginId: string): Promise { + return this.impl.getBaseUrl(pluginId); + } + + async getExternalBaseUrl(pluginId: string): Promise { + return this.impl.getExternalBaseUrl(pluginId); + } +} /** * SingleHostDiscovery is a basic PluginEndpointDiscovery implementation @@ -138,13 +176,13 @@ export const HostDiscovery = _HostDiscovery; * @public * @deprecated Use `HostDiscovery` from `@backstage/backend-defaults/discovery` instead */ -export const SingleHostDiscovery = _HostDiscovery; +export { HostDiscovery as SingleHostDiscovery }; /** * @public * @deprecated Use `CacheManager` from the `@backstage/backend-defaults` package instead */ -export const CacheManager = _CacheManager; +export class CacheManager extends _CacheManager {} /** * @public @@ -257,79 +295,79 @@ export const isChildPath = _isChildPath; * @public * @deprecated Import from `@backstage/backend-defaults/urlReader` instead */ -export const AzureUrlReader = _AzureUrlReader; +export class AzureUrlReader extends _AzureUrlReader {} /** * @public * @deprecated Import from `@backstage/backend-defaults/urlReader` instead */ -export const BitbucketCloudUrlReader = _BitbucketCloudUrlReader; +export class BitbucketCloudUrlReader extends _BitbucketCloudUrlReader {} /** * @public * @deprecated Import from `@backstage/backend-defaults/urlReader` instead */ -export const BitbucketUrlReader = _BitbucketUrlReader; +export class BitbucketUrlReader extends _BitbucketUrlReader {} /** * @public * @deprecated Import from `@backstage/backend-defaults/urlReader` instead */ -export const BitbucketServerUrlReader = _BitbucketServerUrlReader; +export class BitbucketServerUrlReader extends _BitbucketServerUrlReader {} /** * @public * @deprecated Import from `@backstage/backend-defaults/urlReader` instead */ -export const GerritUrlReader = _GerritUrlReader; +export class GerritUrlReader extends _GerritUrlReader {} /** * @public * @deprecated Import from `@backstage/backend-defaults/urlReader` instead */ -export const GithubUrlReader = _GithubUrlReader; +export class GithubUrlReader extends _GithubUrlReader {} /** * @public * @deprecated Import from `@backstage/backend-defaults/urlReader` instead */ -export const GitlabUrlReader = _GitlabUrlReader; +export class GitlabUrlReader extends _GitlabUrlReader {} /** * @public * @deprecated Import from `@backstage/backend-defaults/urlReader` instead */ -export const GiteaUrlReader = _GiteaUrlReader; +export class GiteaUrlReader extends _GiteaUrlReader {} /** * @public * @deprecated Import from `@backstage/backend-defaults/urlReader` instead */ -export const HarnessUrlReader = _HarnessUrlReader; +export class HarnessUrlReader extends _HarnessUrlReader {} /** * @public * @deprecated Import from `@backstage/backend-defaults/urlReader` instead */ -export const AwsS3UrlReader = _AwsS3UrlReader; +export class AwsS3UrlReader extends _AwsS3UrlReader {} /** * @public * @deprecated Import from `@backstage/backend-defaults/urlReader` instead */ -export const FetchUrlReader = _FetchUrlReader; +export class FetchUrlReader extends _FetchUrlReader {} /** * @public * @deprecated Import from `@backstage/backend-defaults/urlReader` instead */ -export const UrlReaders = _UrlReaders; +export class UrlReaders extends _UrlReaders {} /** * @public * @deprecated Import from `@backstage/backend-defaults/urlReader` instead */ -export const ReadUrlResponseFactory = _ReadUrlResponseFactory; +export class ReadUrlResponseFactory extends _ReadUrlResponseFactory {} /** * @public