import { JsonObject, Expand } from '@backstage/types'; import { Config } from '@backstage/config'; /** @public */ type LookupStrategy = 'host' | 'aws'; /** * Restricts an auth entry to only be handed out to the given plugins. * * @public */ type ConnectionAuthMatch = { plugins: string[]; }; /** * The shape of an auth entry as written in configuration: the fields declared * by the auth method's own schema plus the framework-managed `title` and * `match` fields. * * @public */ type ConfiguredConnectionAuth = M extends { method: infer TMethod extends string; configSchema: { parse: (...args: any[]) => infer TConfig; }; } ? Expand<{ method: TMethod; title?: string; match?: ConnectionAuthMatch; } & TConfig> : never; /** * A resolved auth entry as handed to plugins and `matchAuth` implementations: * the fields declared by the auth method's own schema plus a guaranteed * display title. * * @public */ type ConnectionAuthValue = TAuthConfig extends any ? Expand : never; /** * A schema that can validate values and expose a JSON-serializable schema. * * @public */ type PortableSchema = { /** Parses an input value into the validated output type. */ parse: (input: TInput) => TOutput; /** Returns a defensive copy of the JSON Schema representation. */ schema: () => { schema: JsonObject; }; }; /** * Describes a connection type and its portable configuration schemas. * * @public */ type ConnectionType = { type: T['type']; title: string; cardinality: T['cardinality']; lookupStrategy: T['lookupStrategy']; /** Schema for a complete connection configuration. */ configSchema: PortableSchema; /** Supported auth methods and their method-specific configuration schemas. */ authMethods: readonly (T['auth'][number] extends infer TAuth ? TAuth extends { method: string; } ? { method: TAuth['method']; title: string; configSchema: PortableSchema>, unknown>; } : never : never)[]; /** Type-level accessor for the query shape accepted by `find()`. */ readonly query: T['query']; /** * Type-level accessor for the configured auth entry shapes. Each entry is * the method discriminator plus the fields declared by that method's own * config schema; framework-managed fields such as `title` and `match` are * added by the shapes that need them rather than being part of the entries * themselves. */ readonly auth: T['auth']; matchAuth?(authMethods: ConnectionAuthValue[], query: T['query']): ConnectionAuthValue | undefined; /** * Validates the connection as a whole, after each schema has accepted * its own part. * * Use this for rules that no single auth entry can check by itself, for * example "account IDs must be unique across entries". Receives the * parsed connection config and all parsed auth entries, each including * its plugin `match` so that rules can take scoping into account; throw * an error to reject the connection. */ validate?(connection: { config: T['configSchema']; auth: readonly Expand[]; }): void; }; /** @public */ type ConnectionAuthMethodKey = LookupConnectionType['authMethods'][number]['method']; /** @public */ declare const connectionTypes: { readonly aws: ConnectionType<{ type: "aws"; cardinality: "singleton"; lookupStrategy: "aws"; query: { accountId?: string; arn?: string; }; configSchema: { roleName?: string | undefined; partition?: string | undefined; region?: string | undefined; externalId?: string | undefined; webIdentityTokenFile?: string | undefined; }; auth: readonly { method: "account"; accountId?: string | undefined; mainAccount?: boolean | undefined; accessKeyId?: string | undefined; secretAccessKey?: string | undefined; profile?: string | undefined; roleName?: string | undefined; partition?: string | undefined; region?: string | undefined; externalId?: string | undefined; webIdentityTokenFile?: string | undefined; }[]; }>; readonly 'aws-codecommit': ConnectionType<{ type: "aws-codecommit"; cardinality: "multiton"; lookupStrategy: "host"; query: { url: string; }; configSchema: { host: string; region: string; }; auth: readonly ({ method: "accessKey"; accessKeyId: string; secretAccessKey: string; } | { method: "assumeRole"; roleArn: string; externalId?: string | undefined; })[]; }>; readonly 'aws-s3': ConnectionType<{ type: "aws-s3"; cardinality: "multiton"; lookupStrategy: "host"; query: { url: string; }; configSchema: { host: string; endpoint?: string | undefined; s3ForcePathStyle?: boolean | undefined; }; auth: readonly ({ method: "none"; } | { method: "accessKey"; accessKeyId: string; secretAccessKey: string; } | { method: "assumeRole"; roleArn: string; externalId?: string | undefined; })[]; }>; readonly 'azure-blob-storage': ConnectionType<{ type: "azure-blob-storage"; cardinality: "multiton"; lookupStrategy: "host"; query: { url: string; }; configSchema: { host: string; accountName?: string | undefined; endpoint?: string | undefined; endpointSuffix?: string | undefined; }; auth: readonly ({ method: "none"; } | { method: "accountKey"; accountKey: string; } | { method: "sasToken"; sasToken: string; } | { method: "connectionString"; connectionString: string; } | { method: "aadCredential"; clientId: string; tenantId: string; clientSecret: string; })[]; }>; readonly azure: ConnectionType<{ type: "azure"; cardinality: "multiton"; lookupStrategy: "host"; query: { url: string; }; configSchema: { host: string; }; auth: readonly ({ method: "none"; } | { method: "pat"; personalAccessToken: string; orgs?: string[] | undefined; } | { method: "clientCredentials"; clientId: string; clientSecret: string; tenantId: string; orgs?: string[] | undefined; } | { method: "managedIdentity"; clientId: string; tenantId?: string | undefined; managedIdentityClientId?: string | undefined; orgs?: string[] | undefined; })[]; }>; readonly 'bitbucket-cloud': ConnectionType<{ type: "bitbucket-cloud"; cardinality: "multiton"; lookupStrategy: "host"; query: { url: string; }; configSchema: { host: string; }; auth: readonly ({ method: "none"; } | { method: "token"; username: string; token: string; } | { method: "appPassword"; username: string; appPassword: string; } | { method: "oauth"; clientId: string; clientSecret: string; })[]; }>; readonly 'bitbucket-server': ConnectionType<{ type: "bitbucket-server"; cardinality: "multiton"; lookupStrategy: "host"; query: { url: string; }; configSchema: { host: string; apiBaseUrl?: string | undefined; }; auth: readonly ({ method: "none"; } | { method: "token"; token: string; } | { method: "basic"; username: string; password: string; })[]; }>; readonly gerrit: ConnectionType<{ type: "gerrit"; cardinality: "multiton"; lookupStrategy: "host"; query: { url: string; }; configSchema: { host: string; gitilesBaseUrl: string; baseUrl?: string | undefined; cloneUrl?: string | undefined; }; auth: readonly ({ method: "none"; } | { method: "basic"; username: string; password: string; })[]; }>; readonly gitea: ConnectionType<{ type: "gitea"; cardinality: "multiton"; lookupStrategy: "host"; query: { url: string; }; configSchema: { host: string; baseUrl?: string | undefined; }; auth: readonly ({ method: "none"; } | { method: "basic"; username: string; password: string; })[]; }>; readonly github: ConnectionType<{ type: "github"; cardinality: "multiton"; lookupStrategy: "host"; query: { url: string; }; configSchema: { host: string; apiBaseUrl?: string | undefined; rawBaseUrl?: string | undefined; }; auth: readonly ({ method: "none"; } | { method: "token"; token: string; } | { method: "app"; appId: string | number; privateKey: string; clientId: string; clientSecret: string; webhookSecret?: string | undefined; publicAccess?: boolean | undefined; orgs?: string[] | undefined; })[]; }>; readonly gitlab: ConnectionType<{ type: "gitlab"; cardinality: "multiton"; lookupStrategy: "host"; query: { url: string; }; configSchema: { host: string; apiBaseUrl?: string | undefined; baseUrl?: string | undefined; }; auth: readonly ({ method: "none"; } | { method: "token"; token: string; })[]; }>; readonly 'google-gcs': ConnectionType<{ type: "google-gcs"; cardinality: "multiton"; lookupStrategy: "host"; query: { url: string; }; configSchema: { host: string; }; auth: readonly ({ method: "none"; } | { method: "serviceAccount"; clientEmail: string; privateKey: string; })[]; }>; readonly harness: ConnectionType<{ type: "harness"; cardinality: "multiton"; lookupStrategy: "host"; query: { url: string; }; configSchema: { host: string; }; auth: readonly { method: "token"; token: string; apiKey?: string | undefined; }[]; }>; }; /** @public */ type ConnectionTypeKey = keyof typeof connectionTypes; /** @public */ type LookupConnectionType = T extends ConnectionTypeKey ? (typeof connectionTypes)[T] : T; /** @public */ type AuthValue = ConnectionAuthValue['auth'][number]>; /** @public */ type Connection = { type: LookupConnectionType['type']; title: string; auth: string extends TAuthMethod ? AuthValue[] : Extract, { method: TAuthMethod; }>; } & ReturnType['configSchema']['parse']>; /** @public */ interface ConnectionsService { find>(options: { type: TType; query: LookupConnectionType['query']; authMethods: readonly [TAuthMethod, ...TAuthMethod[]]; }): Promise>; } /** * The shape of a fully validated connection as read from configuration, * before any plugin filtering has been applied: the fields declared by the * connection type's config schema plus the framework-managed `type`, `title`, * `match`, and `auth` fields. * * @public */ type ConfiguredConnection = ReturnType['configSchema']['parse']> & { type: LookupConnectionType['type']; title?: string; match?: { plugins: string[]; }; auth: ConfiguredConnectionAuth['authMethods'][number]>[]; }; /** * Builds the effective list of connections from configuration. * * @remarks * * Converts legacy `integrations` config (and the top-level `aws` config) into * connections and merges them with connections declared explicitly under * `connections`. Explicit connections take precedence: if a connection type * has any explicit entries, all legacy entries of that type are ignored. * Duplicate legacy entries that resolve to the same connection are dropped, * keeping the first entry, to match the legacy lookup behavior. * * The returned connections are fully validated against each connection type's * schemas and have default connection and auth method titles assigned. * * An `InputError` is thrown if any part of the configuration is invalid, for * example when a connection fails schema validation or when multiple * connections of the same type resolve to the same identity. * * @public */ declare function buildConnectionsFromConfig(options: { config: Config; logger?: { debug(message: string): void; warn(message: string): void; }; }): ConfiguredConnection[]; export { buildConnectionsFromConfig, connectionTypes }; export type { AuthValue, ConfiguredConnection, ConfiguredConnectionAuth, Connection, ConnectionAuthMatch, ConnectionAuthMethodKey, ConnectionAuthValue, ConnectionType, ConnectionTypeKey, ConnectionsService, LookupConnectionType, LookupStrategy, PortableSchema };