@backstage/backend-defaults 0.5.3-next.0 → 0.5.3-next.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +41 -0
- package/auth/package.json +1 -1
- package/cache/package.json +1 -1
- package/database/package.json +1 -1
- package/discovery/package.json +1 -1
- package/dist/CreateBackend.cjs.js.map +1 -1
- package/dist/PackageDiscoveryService.cjs.js.map +1 -1
- package/dist/discoveryFeatureLoader.cjs.js.map +1 -1
- package/dist/entrypoints/auth/DefaultAuthService.cjs.js.map +1 -1
- package/dist/entrypoints/auth/JwksClient.cjs.js.map +1 -1
- package/dist/entrypoints/auth/authServiceFactory.cjs.js.map +1 -1
- package/dist/entrypoints/auth/external/ExternalTokenHandler.cjs.js.map +1 -1
- package/dist/entrypoints/auth/external/helpers.cjs.js.map +1 -1
- package/dist/entrypoints/auth/external/jwks.cjs.js.map +1 -1
- package/dist/entrypoints/auth/external/legacy.cjs.js.map +1 -1
- package/dist/entrypoints/auth/external/static.cjs.js.map +1 -1
- package/dist/entrypoints/auth/helpers.cjs.js.map +1 -1
- package/dist/entrypoints/auth/plugin/PluginTokenHandler.cjs.js.map +1 -1
- package/dist/entrypoints/auth/plugin/keys/DatabaseKeyStore.cjs.js.map +1 -1
- package/dist/entrypoints/auth/plugin/keys/DatabasePluginKeySource.cjs.js.map +1 -1
- package/dist/entrypoints/auth/plugin/keys/StaticConfigPluginKeySource.cjs.js.map +1 -1
- package/dist/entrypoints/auth/plugin/keys/createPluginKeySource.cjs.js.map +1 -1
- package/dist/entrypoints/auth/user/UserTokenHandler.cjs.js.map +1 -1
- package/dist/entrypoints/cache/CacheClient.cjs.js.map +1 -1
- package/dist/entrypoints/cache/CacheManager.cjs.js.map +1 -1
- package/dist/entrypoints/cache/cacheServiceFactory.cjs.js.map +1 -1
- package/dist/entrypoints/cache/types.cjs.js.map +1 -1
- package/dist/entrypoints/database/DatabaseManager.cjs.js +1 -3
- package/dist/entrypoints/database/DatabaseManager.cjs.js.map +1 -1
- package/dist/entrypoints/database/connectors/defaultNameOverride.cjs.js.map +1 -1
- package/dist/entrypoints/database/connectors/defaultSchemaOverride.cjs.js.map +1 -1
- package/dist/entrypoints/database/connectors/mergeDatabaseConfig.cjs.js.map +1 -1
- package/dist/entrypoints/database/connectors/mysql.cjs.js.map +1 -1
- package/dist/entrypoints/database/connectors/postgres.cjs.js.map +1 -1
- package/dist/entrypoints/database/connectors/sqlite3.cjs.js.map +1 -1
- package/dist/entrypoints/database/databaseServiceFactory.cjs.js.map +1 -1
- package/dist/entrypoints/discovery/HostDiscovery.cjs.js.map +1 -1
- package/dist/entrypoints/discovery/discoveryServiceFactory.cjs.js.map +1 -1
- package/dist/entrypoints/httpAuth/httpAuthServiceFactory.cjs.js.map +1 -1
- package/dist/entrypoints/httpRouter/createAuthIntegrationRouter.cjs.js.map +1 -1
- package/dist/entrypoints/httpRouter/createCookieAuthRefreshMiddleware.cjs.js.map +1 -1
- package/dist/entrypoints/httpRouter/createCredentialsBarrier.cjs.js.map +1 -1
- package/dist/entrypoints/httpRouter/createLifecycleMiddleware.cjs.js.map +1 -1
- package/dist/entrypoints/httpRouter/httpRouterServiceFactory.cjs.js.map +1 -1
- package/dist/entrypoints/lifecycle/lifecycleServiceFactory.cjs.js.map +1 -1
- package/dist/entrypoints/logger/loggerServiceFactory.cjs.js.map +1 -1
- package/dist/entrypoints/permissions/permissionsServiceFactory.cjs.js.map +1 -1
- package/dist/entrypoints/rootConfig/createConfigSecretEnumerator.cjs.js.map +1 -1
- package/dist/entrypoints/rootConfig/rootConfigServiceFactory.cjs.js.map +1 -1
- package/dist/entrypoints/rootHealth/rootHealthServiceFactory.cjs.js.map +1 -1
- package/dist/entrypoints/rootHttpRouter/DefaultRootHttpRouter.cjs.js.map +1 -1
- package/dist/entrypoints/rootHttpRouter/createHealthRouter.cjs.js.map +1 -1
- package/dist/entrypoints/rootHttpRouter/http/MiddlewareFactory.cjs.js.map +1 -1
- package/dist/entrypoints/rootHttpRouter/http/applyInternalErrorFilter.cjs.js.map +1 -1
- package/dist/entrypoints/rootHttpRouter/http/config.cjs.js.map +1 -1
- package/dist/entrypoints/rootHttpRouter/http/createHttpServer.cjs.js.map +1 -1
- package/dist/entrypoints/rootHttpRouter/http/getGeneratedCertificate.cjs.js.map +1 -1
- package/dist/entrypoints/rootHttpRouter/http/readCorsOptions.cjs.js.map +1 -1
- package/dist/entrypoints/rootHttpRouter/http/readHelmetOptions.cjs.js.map +1 -1
- package/dist/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.cjs.js.map +1 -1
- package/dist/entrypoints/rootLifecycle/rootLifecycleServiceFactory.cjs.js.map +1 -1
- package/dist/entrypoints/rootLogger/WinstonLogger.cjs.js.map +1 -1
- package/dist/entrypoints/rootLogger/rootLoggerServiceFactory.cjs.js.map +1 -1
- package/dist/entrypoints/scheduler/database/migrateBackendTasks.cjs.js.map +1 -1
- package/dist/entrypoints/scheduler/database/tables.cjs.js.map +1 -1
- package/dist/entrypoints/scheduler/lib/DefaultSchedulerService.cjs.js.map +1 -1
- package/dist/entrypoints/scheduler/lib/LocalTaskWorker.cjs.js.map +1 -1
- package/dist/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.cjs.js.map +1 -1
- package/dist/entrypoints/scheduler/lib/PluginTaskSchedulerJanitor.cjs.js.map +1 -1
- package/dist/entrypoints/scheduler/lib/TaskWorker.cjs.js.map +1 -1
- package/dist/entrypoints/scheduler/lib/types.cjs.js.map +1 -1
- package/dist/entrypoints/scheduler/lib/util.cjs.js.map +1 -1
- package/dist/entrypoints/scheduler/schedulerServiceFactory.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/lib/AwsCodeCommitUrlReader.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/lib/AwsS3UrlReader.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/lib/AzureUrlReader.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/lib/BitbucketCloudUrlReader.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/lib/BitbucketServerUrlReader.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/lib/BitbucketUrlReader.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/lib/FetchUrlReader.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/lib/GerritUrlReader.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/lib/GiteaUrlReader.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/lib/GithubUrlReader.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/lib/GitlabUrlReader.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/lib/GoogleGcsUrlReader.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/lib/HarnessUrlReader.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/lib/ReadUrlResponseFactory.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/lib/UrlReaderPredicateMux.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/lib/UrlReaders.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/lib/tree/ReadTreeResponseFactory.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/lib/tree/ReadableArrayResponse.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/lib/tree/TarArchiveResponse.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/lib/tree/ZipArchiveResponse.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/lib/tree/util.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/lib/util.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/urlReaderServiceFactory.cjs.js.map +1 -1
- package/dist/entrypoints/userInfo/DefaultUserInfoService.cjs.js.map +1 -1
- package/dist/entrypoints/userInfo/userInfoServiceFactory.cjs.js.map +1 -1
- package/dist/lib/escapeRegExp.cjs.js.map +1 -1
- package/dist/package.json.cjs.js +1 -1
- package/httpAuth/package.json +1 -1
- package/httpRouter/package.json +1 -1
- package/lifecycle/package.json +1 -1
- package/logger/package.json +1 -1
- package/package.json +12 -12
- package/permissions/package.json +1 -1
- package/rootConfig/package.json +1 -1
- package/rootHealth/package.json +1 -1
- package/rootHttpRouter/package.json +1 -1
- package/rootLifecycle/package.json +1 -1
- package/rootLogger/package.json +1 -1
- package/scheduler/package.json +1 -1
- package/urlReader/package.json +1 -1
- package/userInfo/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postgres.cjs.js","sources":["../../../../src/entrypoints/database/connectors/postgres.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { LifecycleService, LoggerService } from '@backstage/backend-plugin-api';\nimport { Config, ConfigReader } from '@backstage/config';\nimport { ForwardedError } from '@backstage/errors';\nimport { JsonObject } from '@backstage/types';\nimport knexFactory, { Knex } from 'knex';\nimport { merge, omit } from 'lodash';\nimport limiterFactory from 'p-limit';\nimport { Client } from 'pg';\nimport { Connector } from '../types';\nimport defaultNameOverride from './defaultNameOverride';\nimport defaultSchemaOverride from './defaultSchemaOverride';\nimport { mergeDatabaseConfig } from './mergeDatabaseConfig';\nimport format from 'pg-format';\n\n// Limits the number of concurrent DDL operations to 1\nconst ddlLimiter = limiterFactory(1);\n\n/**\n * Creates a knex postgres database connection\n *\n * @param dbConfig - The database config\n * @param overrides - Additional options to merge with the config\n */\nexport function createPgDatabaseClient(\n dbConfig: Config,\n overrides?: Knex.Config,\n) {\n const knexConfig = buildPgDatabaseConfig(dbConfig, overrides);\n const database = knexFactory(knexConfig);\n\n const role = dbConfig.getOptionalString('role');\n\n if (role) {\n database.client.pool.on(\n 'createSuccess',\n async (_event: number, pgClient: Client) => {\n const query = format('SET ROLE %I', role);\n await pgClient.query(query);\n },\n );\n }\n return database;\n}\n\n/**\n * Builds a knex postgres database connection\n *\n * @param dbConfig - The database config\n * @param overrides - Additional options to merge with the config\n */\nexport function buildPgDatabaseConfig(\n dbConfig: Config,\n overrides?: Knex.Config,\n) {\n return mergeDatabaseConfig(\n dbConfig.get(),\n {\n connection: getPgConnectionConfig(dbConfig, !!overrides),\n useNullAsDefault: true,\n },\n overrides,\n );\n}\n\n/**\n * Gets the postgres connection config\n *\n * @param dbConfig - The database config\n * @param parseConnectionString - Flag to explicitly control connection string parsing\n */\nexport function getPgConnectionConfig(\n dbConfig: Config,\n parseConnectionString?: boolean,\n): Knex.PgConnectionConfig | string {\n const connection = dbConfig.get('connection') as any;\n const isConnectionString =\n typeof connection === 'string' || connection instanceof String;\n const autoParse = typeof parseConnectionString !== 'boolean';\n\n const shouldParseConnectionString = autoParse\n ? isConnectionString\n : parseConnectionString && isConnectionString;\n\n return shouldParseConnectionString\n ? parsePgConnectionString(connection as string)\n : connection;\n}\n\n/**\n * Parses a connection string using pg-connection-string\n *\n * @param connectionString - The postgres connection string\n */\nexport function parsePgConnectionString(connectionString: string) {\n const parse = requirePgConnectionString();\n return parse(connectionString);\n}\n\nfunction requirePgConnectionString() {\n try {\n return require('pg-connection-string').parse;\n } catch (e) {\n throw new ForwardedError(\"Postgres: Install 'pg-connection-string'\", e);\n }\n}\n\n/**\n * Creates the missing Postgres database if it does not exist\n *\n * @param dbConfig - The database config\n * @param databases - The name of the databases to create\n */\nexport async function ensurePgDatabaseExists(\n dbConfig: Config,\n ...databases: Array<string>\n) {\n const admin = createPgDatabaseClient(dbConfig, {\n connection: {\n database: 'postgres',\n },\n pool: {\n min: 0,\n acquireTimeoutMillis: 10000,\n },\n });\n\n try {\n const ensureDatabase = async (database: string) => {\n const result = await admin\n .from('pg_database')\n .where('datname', database)\n .count<Record<string, { count: string }>>();\n\n if (parseInt(result[0].count, 10) > 0) {\n return;\n }\n\n await admin.raw(`CREATE DATABASE ??`, [database]);\n };\n\n await Promise.all(\n databases.map(async database => {\n // For initial setup we use a smaller timeout but several retries. Given that this\n // is a separate connection pool we should never really run into issues with connection\n // acquisition timeouts, but we do anyway. This might be a bug in knex or some other dependency.\n let lastErr: Error | undefined = undefined;\n for (let i = 0; i < 3; i++) {\n try {\n return await ddlLimiter(() => ensureDatabase(database));\n } catch (err) {\n lastErr = err;\n }\n await new Promise(resolve => setTimeout(resolve, 100));\n }\n throw lastErr;\n }),\n );\n } finally {\n await admin.destroy();\n }\n}\n\n/**\n * Creates the missing Postgres schema if it does not exist\n *\n * @param dbConfig - The database config\n * @param schemas - The name of the schemas to create\n */\nexport async function ensurePgSchemaExists(\n dbConfig: Config,\n ...schemas: Array<string>\n): Promise<void> {\n const admin = createPgDatabaseClient(dbConfig);\n const role = dbConfig.getOptionalString('role');\n\n try {\n const ensureSchema = async (database: string) => {\n if (role) {\n await admin.raw(`CREATE SCHEMA IF NOT EXISTS ?? AUTHORIZATION ??`, [\n database,\n role,\n ]);\n } else {\n await admin.raw(`CREATE SCHEMA IF NOT EXISTS ??`, [database]);\n }\n };\n\n await Promise.all(\n schemas.map(database => ddlLimiter(() => ensureSchema(database))),\n );\n } finally {\n await admin.destroy();\n }\n}\n\n/**\n * Drops the Postgres databases.\n *\n * @param dbConfig - The database config\n * @param databases - The name of the databases to drop\n */\nexport async function dropPgDatabase(\n dbConfig: Config,\n ...databases: Array<string>\n) {\n const admin = createPgDatabaseClient(dbConfig);\n try {\n await Promise.all(\n databases.map(async database => {\n await ddlLimiter(() => admin.raw(`DROP DATABASE ??`, [database]));\n }),\n );\n } finally {\n await admin.destroy();\n }\n}\n\n/**\n * Provides a config lookup path for a plugin's config block.\n */\nfunction pluginPath(pluginId: string): string {\n return `plugin.${pluginId}`;\n}\n\nfunction normalizeConnection(\n connection: Knex.StaticConnectionConfig | JsonObject | string | undefined,\n): Partial<Knex.StaticConnectionConfig> {\n if (typeof connection === 'undefined' || connection === null) {\n return {};\n }\n\n return typeof connection === 'string' || connection instanceof String\n ? parsePgConnectionString(connection as string)\n : connection;\n}\n\nexport class PgConnector implements Connector {\n constructor(\n private readonly config: Config,\n private readonly prefix: string,\n ) {}\n\n async getClient(\n pluginId: string,\n _deps: {\n logger: LoggerService;\n lifecycle: LifecycleService;\n },\n ): Promise<Knex> {\n const pluginConfig = new ConfigReader(\n this.getConfigForPlugin(pluginId) as JsonObject,\n );\n\n const databaseName = this.getDatabaseName(pluginId);\n if (databaseName && this.getEnsureExistsConfig(pluginId)) {\n try {\n await ensurePgDatabaseExists(pluginConfig, databaseName);\n } catch (error) {\n throw new Error(\n `Failed to connect to the database to make sure that '${databaseName}' exists, ${error}`,\n );\n }\n }\n\n let schemaOverrides;\n if (this.getPluginDivisionModeConfig() === 'schema') {\n schemaOverrides = defaultSchemaOverride(pluginId);\n if (\n this.getEnsureSchemaExistsConfig(pluginId) ||\n this.getEnsureExistsConfig(pluginId)\n ) {\n try {\n await ensurePgSchemaExists(pluginConfig, pluginId);\n } catch (error) {\n throw new Error(\n `Failed to connect to the database to make sure that schema for plugin '${pluginId}' exists, ${error}`,\n );\n }\n }\n }\n\n const databaseClientOverrides = mergeDatabaseConfig(\n {},\n this.getDatabaseOverrides(pluginId),\n schemaOverrides,\n );\n\n const client = createPgDatabaseClient(\n pluginConfig,\n databaseClientOverrides,\n );\n\n return client;\n }\n\n /**\n * Provides the canonical database name for a given plugin.\n *\n * This method provides the effective database name which is determined using global\n * and plugin specific database config. If no explicit database name is configured\n * and `pluginDivisionMode` is not `schema`, this method will provide a generated name\n * which is the pluginId prefixed with 'backstage_plugin_'. If `pluginDivisionMode` is\n * `schema`, it will fallback to using the default database for the knex instance.\n *\n * @param pluginId - Lookup the database name for given plugin\n * @returns String representing the plugin's database name\n */\n private getDatabaseName(pluginId: string): string | undefined {\n const connection = this.getConnectionConfig(pluginId);\n\n const databaseName = (connection as Knex.ConnectionConfig)?.database;\n\n // `pluginDivisionMode` as `schema` should use overridden databaseName if supplied or fallback to default knex database\n if (this.getPluginDivisionModeConfig() === 'schema') {\n return databaseName;\n }\n\n // all other supported databases should fallback to an auto-prefixed name\n return databaseName ?? `${this.prefix}${pluginId}`;\n }\n\n /**\n * Provides the client type which should be used for a given plugin.\n *\n * The client type is determined by plugin specific config if present.\n * Otherwise the base client is used as the fallback.\n *\n * @param pluginId - Plugin to get the client type for\n * @returns Object with client type returned as `client` and boolean\n * representing whether or not the client was overridden as\n * `overridden`\n */\n private getClientType(pluginId: string): {\n client: string;\n overridden: boolean;\n } {\n const pluginClient = this.config.getOptionalString(\n `${pluginPath(pluginId)}.client`,\n );\n\n const baseClient = this.config.getString('client');\n const client = pluginClient ?? baseClient;\n return {\n client,\n overridden: client !== baseClient,\n };\n }\n\n private getRoleConfig(pluginId: string): string | undefined {\n return (\n this.config.getOptionalString(`${pluginPath(pluginId)}.role`) ??\n this.config.getOptionalString('role')\n );\n }\n\n /**\n * Provides the knexConfig which should be used for a given plugin.\n *\n * @param pluginId - Plugin to get the knexConfig for\n * @returns The merged knexConfig value or undefined if it isn't specified\n */\n private getAdditionalKnexConfig(pluginId: string): JsonObject | undefined {\n const pluginConfig = this.config\n .getOptionalConfig(`${pluginPath(pluginId)}.knexConfig`)\n ?.get<JsonObject>();\n\n const baseConfig = this.config\n .getOptionalConfig('knexConfig')\n ?.get<JsonObject>();\n\n return merge(baseConfig, pluginConfig);\n }\n\n private getEnsureExistsConfig(pluginId: string): boolean {\n const baseConfig = this.config.getOptionalBoolean('ensureExists') ?? true;\n return (\n this.config.getOptionalBoolean(`${pluginPath(pluginId)}.ensureExists`) ??\n baseConfig\n );\n }\n\n private getEnsureSchemaExistsConfig(pluginId: string): boolean {\n const baseConfig =\n this.config.getOptionalBoolean('ensureSchemaExists') ?? false;\n return (\n this.config.getOptionalBoolean(\n `${pluginPath(pluginId)}.getEnsureSchemaExistsConfig`,\n ) ?? baseConfig\n );\n }\n\n private getPluginDivisionModeConfig(): string {\n return this.config.getOptionalString('pluginDivisionMode') ?? 'database';\n }\n\n /**\n * Provides a Knex connection plugin config by combining base and plugin\n * config.\n *\n * This method provides a baseConfig for a plugin database connector. If the\n * client type has not been overridden, the global connection config will be\n * included with plugin specific config as the base. Values from the plugin\n * connection take precedence over the base. Base database name is omitted\n * unless `pluginDivisionMode` is set to `schema`.\n */\n private getConnectionConfig(pluginId: string): Knex.StaticConnectionConfig {\n const { overridden } = this.getClientType(pluginId);\n\n let baseConnection = normalizeConnection(this.config.get('connection'));\n\n // Databases cannot be shared unless the `pluginDivisionMode` is set to `schema`. The\n // `database` property from the base connection is omitted unless `pluginDivisionMode`\n // is set to `schema`.\n if (this.getPluginDivisionModeConfig() !== 'schema') {\n baseConnection = omit(baseConnection, 'database');\n }\n\n // get and normalize optional plugin specific database connection\n const connection = normalizeConnection(\n this.config.getOptional(`${pluginPath(pluginId)}.connection`),\n );\n\n (\n baseConnection as Knex.PgConnectionConfig\n ).application_name ||= `backstage_plugin_${pluginId}`;\n\n return {\n // include base connection if client type has not been overridden\n ...(overridden ? {} : baseConnection),\n ...connection,\n } as Knex.StaticConnectionConfig;\n }\n\n /**\n * Provides a Knex database config for a given plugin.\n *\n * This method provides a Knex configuration object along with the plugin's\n * client type.\n *\n * @param pluginId - The plugin that the database config should correspond with\n */\n private getConfigForPlugin(pluginId: string): Knex.Config {\n const { client } = this.getClientType(pluginId);\n const role = this.getRoleConfig(pluginId);\n\n return {\n ...this.getAdditionalKnexConfig(pluginId),\n client,\n connection: this.getConnectionConfig(pluginId),\n ...(role && { role }),\n };\n }\n\n /**\n * Provides a partial `Knex.Config`• database name override for a given plugin.\n *\n * @param pluginId - Target plugin to get database name override\n * @returns Partial `Knex.Config` with database name override\n */\n private getDatabaseOverrides(pluginId: string): Knex.Config {\n const databaseName = this.getDatabaseName(pluginId);\n return databaseName ? defaultNameOverride(databaseName) : {};\n }\n}\n"],"names":["limiterFactory","knexFactory","format","mergeDatabaseConfig","ForwardedError","ConfigReader","defaultSchemaOverride","merge","omit","defaultNameOverride"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"postgres.cjs.js","sources":["../../../../src/entrypoints/database/connectors/postgres.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { LifecycleService, LoggerService } from '@backstage/backend-plugin-api';\nimport { Config, ConfigReader } from '@backstage/config';\nimport { ForwardedError } from '@backstage/errors';\nimport { JsonObject } from '@backstage/types';\nimport knexFactory, { Knex } from 'knex';\nimport { merge, omit } from 'lodash';\nimport limiterFactory from 'p-limit';\nimport { Client } from 'pg';\nimport { Connector } from '../types';\nimport defaultNameOverride from './defaultNameOverride';\nimport defaultSchemaOverride from './defaultSchemaOverride';\nimport { mergeDatabaseConfig } from './mergeDatabaseConfig';\nimport format from 'pg-format';\n\n// Limits the number of concurrent DDL operations to 1\nconst ddlLimiter = limiterFactory(1);\n\n/**\n * Creates a knex postgres database connection\n *\n * @param dbConfig - The database config\n * @param overrides - Additional options to merge with the config\n */\nexport function createPgDatabaseClient(\n dbConfig: Config,\n overrides?: Knex.Config,\n) {\n const knexConfig = buildPgDatabaseConfig(dbConfig, overrides);\n const database = knexFactory(knexConfig);\n\n const role = dbConfig.getOptionalString('role');\n\n if (role) {\n database.client.pool.on(\n 'createSuccess',\n async (_event: number, pgClient: Client) => {\n const query = format('SET ROLE %I', role);\n await pgClient.query(query);\n },\n );\n }\n return database;\n}\n\n/**\n * Builds a knex postgres database connection\n *\n * @param dbConfig - The database config\n * @param overrides - Additional options to merge with the config\n */\nexport function buildPgDatabaseConfig(\n dbConfig: Config,\n overrides?: Knex.Config,\n) {\n return mergeDatabaseConfig(\n dbConfig.get(),\n {\n connection: getPgConnectionConfig(dbConfig, !!overrides),\n useNullAsDefault: true,\n },\n overrides,\n );\n}\n\n/**\n * Gets the postgres connection config\n *\n * @param dbConfig - The database config\n * @param parseConnectionString - Flag to explicitly control connection string parsing\n */\nexport function getPgConnectionConfig(\n dbConfig: Config,\n parseConnectionString?: boolean,\n): Knex.PgConnectionConfig | string {\n const connection = dbConfig.get('connection') as any;\n const isConnectionString =\n typeof connection === 'string' || connection instanceof String;\n const autoParse = typeof parseConnectionString !== 'boolean';\n\n const shouldParseConnectionString = autoParse\n ? isConnectionString\n : parseConnectionString && isConnectionString;\n\n return shouldParseConnectionString\n ? parsePgConnectionString(connection as string)\n : connection;\n}\n\n/**\n * Parses a connection string using pg-connection-string\n *\n * @param connectionString - The postgres connection string\n */\nexport function parsePgConnectionString(connectionString: string) {\n const parse = requirePgConnectionString();\n return parse(connectionString);\n}\n\nfunction requirePgConnectionString() {\n try {\n return require('pg-connection-string').parse;\n } catch (e) {\n throw new ForwardedError(\"Postgres: Install 'pg-connection-string'\", e);\n }\n}\n\n/**\n * Creates the missing Postgres database if it does not exist\n *\n * @param dbConfig - The database config\n * @param databases - The name of the databases to create\n */\nexport async function ensurePgDatabaseExists(\n dbConfig: Config,\n ...databases: Array<string>\n) {\n const admin = createPgDatabaseClient(dbConfig, {\n connection: {\n database: 'postgres',\n },\n pool: {\n min: 0,\n acquireTimeoutMillis: 10000,\n },\n });\n\n try {\n const ensureDatabase = async (database: string) => {\n const result = await admin\n .from('pg_database')\n .where('datname', database)\n .count<Record<string, { count: string }>>();\n\n if (parseInt(result[0].count, 10) > 0) {\n return;\n }\n\n await admin.raw(`CREATE DATABASE ??`, [database]);\n };\n\n await Promise.all(\n databases.map(async database => {\n // For initial setup we use a smaller timeout but several retries. Given that this\n // is a separate connection pool we should never really run into issues with connection\n // acquisition timeouts, but we do anyway. This might be a bug in knex or some other dependency.\n let lastErr: Error | undefined = undefined;\n for (let i = 0; i < 3; i++) {\n try {\n return await ddlLimiter(() => ensureDatabase(database));\n } catch (err) {\n lastErr = err;\n }\n await new Promise(resolve => setTimeout(resolve, 100));\n }\n throw lastErr;\n }),\n );\n } finally {\n await admin.destroy();\n }\n}\n\n/**\n * Creates the missing Postgres schema if it does not exist\n *\n * @param dbConfig - The database config\n * @param schemas - The name of the schemas to create\n */\nexport async function ensurePgSchemaExists(\n dbConfig: Config,\n ...schemas: Array<string>\n): Promise<void> {\n const admin = createPgDatabaseClient(dbConfig);\n const role = dbConfig.getOptionalString('role');\n\n try {\n const ensureSchema = async (database: string) => {\n if (role) {\n await admin.raw(`CREATE SCHEMA IF NOT EXISTS ?? AUTHORIZATION ??`, [\n database,\n role,\n ]);\n } else {\n await admin.raw(`CREATE SCHEMA IF NOT EXISTS ??`, [database]);\n }\n };\n\n await Promise.all(\n schemas.map(database => ddlLimiter(() => ensureSchema(database))),\n );\n } finally {\n await admin.destroy();\n }\n}\n\n/**\n * Drops the Postgres databases.\n *\n * @param dbConfig - The database config\n * @param databases - The name of the databases to drop\n */\nexport async function dropPgDatabase(\n dbConfig: Config,\n ...databases: Array<string>\n) {\n const admin = createPgDatabaseClient(dbConfig);\n try {\n await Promise.all(\n databases.map(async database => {\n await ddlLimiter(() => admin.raw(`DROP DATABASE ??`, [database]));\n }),\n );\n } finally {\n await admin.destroy();\n }\n}\n\n/**\n * Provides a config lookup path for a plugin's config block.\n */\nfunction pluginPath(pluginId: string): string {\n return `plugin.${pluginId}`;\n}\n\nfunction normalizeConnection(\n connection: Knex.StaticConnectionConfig | JsonObject | string | undefined,\n): Partial<Knex.StaticConnectionConfig> {\n if (typeof connection === 'undefined' || connection === null) {\n return {};\n }\n\n return typeof connection === 'string' || connection instanceof String\n ? parsePgConnectionString(connection as string)\n : connection;\n}\n\nexport class PgConnector implements Connector {\n constructor(\n private readonly config: Config,\n private readonly prefix: string,\n ) {}\n\n async getClient(\n pluginId: string,\n _deps: {\n logger: LoggerService;\n lifecycle: LifecycleService;\n },\n ): Promise<Knex> {\n const pluginConfig = new ConfigReader(\n this.getConfigForPlugin(pluginId) as JsonObject,\n );\n\n const databaseName = this.getDatabaseName(pluginId);\n if (databaseName && this.getEnsureExistsConfig(pluginId)) {\n try {\n await ensurePgDatabaseExists(pluginConfig, databaseName);\n } catch (error) {\n throw new Error(\n `Failed to connect to the database to make sure that '${databaseName}' exists, ${error}`,\n );\n }\n }\n\n let schemaOverrides;\n if (this.getPluginDivisionModeConfig() === 'schema') {\n schemaOverrides = defaultSchemaOverride(pluginId);\n if (\n this.getEnsureSchemaExistsConfig(pluginId) ||\n this.getEnsureExistsConfig(pluginId)\n ) {\n try {\n await ensurePgSchemaExists(pluginConfig, pluginId);\n } catch (error) {\n throw new Error(\n `Failed to connect to the database to make sure that schema for plugin '${pluginId}' exists, ${error}`,\n );\n }\n }\n }\n\n const databaseClientOverrides = mergeDatabaseConfig(\n {},\n this.getDatabaseOverrides(pluginId),\n schemaOverrides,\n );\n\n const client = createPgDatabaseClient(\n pluginConfig,\n databaseClientOverrides,\n );\n\n return client;\n }\n\n /**\n * Provides the canonical database name for a given plugin.\n *\n * This method provides the effective database name which is determined using global\n * and plugin specific database config. If no explicit database name is configured\n * and `pluginDivisionMode` is not `schema`, this method will provide a generated name\n * which is the pluginId prefixed with 'backstage_plugin_'. If `pluginDivisionMode` is\n * `schema`, it will fallback to using the default database for the knex instance.\n *\n * @param pluginId - Lookup the database name for given plugin\n * @returns String representing the plugin's database name\n */\n private getDatabaseName(pluginId: string): string | undefined {\n const connection = this.getConnectionConfig(pluginId);\n\n const databaseName = (connection as Knex.ConnectionConfig)?.database;\n\n // `pluginDivisionMode` as `schema` should use overridden databaseName if supplied or fallback to default knex database\n if (this.getPluginDivisionModeConfig() === 'schema') {\n return databaseName;\n }\n\n // all other supported databases should fallback to an auto-prefixed name\n return databaseName ?? `${this.prefix}${pluginId}`;\n }\n\n /**\n * Provides the client type which should be used for a given plugin.\n *\n * The client type is determined by plugin specific config if present.\n * Otherwise the base client is used as the fallback.\n *\n * @param pluginId - Plugin to get the client type for\n * @returns Object with client type returned as `client` and boolean\n * representing whether or not the client was overridden as\n * `overridden`\n */\n private getClientType(pluginId: string): {\n client: string;\n overridden: boolean;\n } {\n const pluginClient = this.config.getOptionalString(\n `${pluginPath(pluginId)}.client`,\n );\n\n const baseClient = this.config.getString('client');\n const client = pluginClient ?? baseClient;\n return {\n client,\n overridden: client !== baseClient,\n };\n }\n\n private getRoleConfig(pluginId: string): string | undefined {\n return (\n this.config.getOptionalString(`${pluginPath(pluginId)}.role`) ??\n this.config.getOptionalString('role')\n );\n }\n\n /**\n * Provides the knexConfig which should be used for a given plugin.\n *\n * @param pluginId - Plugin to get the knexConfig for\n * @returns The merged knexConfig value or undefined if it isn't specified\n */\n private getAdditionalKnexConfig(pluginId: string): JsonObject | undefined {\n const pluginConfig = this.config\n .getOptionalConfig(`${pluginPath(pluginId)}.knexConfig`)\n ?.get<JsonObject>();\n\n const baseConfig = this.config\n .getOptionalConfig('knexConfig')\n ?.get<JsonObject>();\n\n return merge(baseConfig, pluginConfig);\n }\n\n private getEnsureExistsConfig(pluginId: string): boolean {\n const baseConfig = this.config.getOptionalBoolean('ensureExists') ?? true;\n return (\n this.config.getOptionalBoolean(`${pluginPath(pluginId)}.ensureExists`) ??\n baseConfig\n );\n }\n\n private getEnsureSchemaExistsConfig(pluginId: string): boolean {\n const baseConfig =\n this.config.getOptionalBoolean('ensureSchemaExists') ?? false;\n return (\n this.config.getOptionalBoolean(\n `${pluginPath(pluginId)}.getEnsureSchemaExistsConfig`,\n ) ?? baseConfig\n );\n }\n\n private getPluginDivisionModeConfig(): string {\n return this.config.getOptionalString('pluginDivisionMode') ?? 'database';\n }\n\n /**\n * Provides a Knex connection plugin config by combining base and plugin\n * config.\n *\n * This method provides a baseConfig for a plugin database connector. If the\n * client type has not been overridden, the global connection config will be\n * included with plugin specific config as the base. Values from the plugin\n * connection take precedence over the base. Base database name is omitted\n * unless `pluginDivisionMode` is set to `schema`.\n */\n private getConnectionConfig(pluginId: string): Knex.StaticConnectionConfig {\n const { overridden } = this.getClientType(pluginId);\n\n let baseConnection = normalizeConnection(this.config.get('connection'));\n\n // Databases cannot be shared unless the `pluginDivisionMode` is set to `schema`. The\n // `database` property from the base connection is omitted unless `pluginDivisionMode`\n // is set to `schema`.\n if (this.getPluginDivisionModeConfig() !== 'schema') {\n baseConnection = omit(baseConnection, 'database');\n }\n\n // get and normalize optional plugin specific database connection\n const connection = normalizeConnection(\n this.config.getOptional(`${pluginPath(pluginId)}.connection`),\n );\n\n (\n baseConnection as Knex.PgConnectionConfig\n ).application_name ||= `backstage_plugin_${pluginId}`;\n\n return {\n // include base connection if client type has not been overridden\n ...(overridden ? {} : baseConnection),\n ...connection,\n } as Knex.StaticConnectionConfig;\n }\n\n /**\n * Provides a Knex database config for a given plugin.\n *\n * This method provides a Knex configuration object along with the plugin's\n * client type.\n *\n * @param pluginId - The plugin that the database config should correspond with\n */\n private getConfigForPlugin(pluginId: string): Knex.Config {\n const { client } = this.getClientType(pluginId);\n const role = this.getRoleConfig(pluginId);\n\n return {\n ...this.getAdditionalKnexConfig(pluginId),\n client,\n connection: this.getConnectionConfig(pluginId),\n ...(role && { role }),\n };\n }\n\n /**\n * Provides a partial `Knex.Config`• database name override for a given plugin.\n *\n * @param pluginId - Target plugin to get database name override\n * @returns Partial `Knex.Config` with database name override\n */\n private getDatabaseOverrides(pluginId: string): Knex.Config {\n const databaseName = this.getDatabaseName(pluginId);\n return databaseName ? defaultNameOverride(databaseName) : {};\n }\n}\n"],"names":["limiterFactory","knexFactory","format","mergeDatabaseConfig","ForwardedError","ConfigReader","defaultSchemaOverride","merge","omit","defaultNameOverride"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite3.cjs.js","sources":["../../../../src/entrypoints/database/connectors/sqlite3.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { DevDataStore } from '@backstage/backend-dev-utils';\nimport { LifecycleService, LoggerService } from '@backstage/backend-plugin-api';\nimport { Config, ConfigReader } from '@backstage/config';\nimport { JsonObject } from '@backstage/types';\nimport { ensureDirSync } from 'fs-extra';\nimport knexFactory, { Knex } from 'knex';\nimport { merge, omit } from 'lodash';\nimport path from 'path';\nimport { Connector } from '../types';\nimport { mergeDatabaseConfig } from './mergeDatabaseConfig';\n\n/**\n * Creates a knex SQLite3 database connection\n *\n * @param dbConfig - The database config\n * @param overrides - Additional options to merge with the config\n */\nexport function createSqliteDatabaseClient(\n pluginId: string,\n dbConfig: Config,\n deps: {\n logger: LoggerService;\n lifecycle: LifecycleService;\n },\n overrides?: Knex.Config,\n) {\n const knexConfig = buildSqliteDatabaseConfig(dbConfig, overrides);\n const connConfig = knexConfig.connection as Knex.Sqlite3ConnectionConfig;\n\n const filename = connConfig.filename ?? ':memory:';\n\n // If storage on disk is used, ensure that the directory exists\n if (filename !== ':memory:') {\n const directory = path.dirname(filename);\n ensureDirSync(directory);\n }\n\n let database: Knex;\n\n if (deps && filename === ':memory:') {\n // The dev store is used during watch mode to store and restore the database\n // across reloads. It is only available when running the backend through\n // `backstage-cli package start`.\n const devStore = DevDataStore.get();\n\n if (devStore) {\n const dataKey = `sqlite3-db-${pluginId}`;\n\n const connectionLoader = async () => {\n // If seed data is available, use it tconnectionLoader restore the database\n const { data: seedData } = await devStore.load(dataKey);\n\n return {\n ...(knexConfig.connection as Knex.Sqlite3ConnectionConfig),\n filename: seedData ?? ':memory:',\n };\n };\n\n database = knexFactory({\n ...knexConfig,\n connection: Object.assign(connectionLoader, {\n // This is a workaround for the knex SQLite driver always warning when using a config loader\n filename: ':memory:',\n }),\n });\n\n // If the dev store is available we save the database state on shutdown\n deps.lifecycle.addShutdownHook(async () => {\n const connection = await database.client.acquireConnection();\n const data = connection.serialize();\n await devStore.save(dataKey, data);\n });\n } else {\n database = knexFactory(knexConfig);\n }\n } else {\n database = knexFactory(knexConfig);\n }\n\n database.client.pool.on('createSuccess', (_eventId: any, resource: any) => {\n resource.run('PRAGMA foreign_keys = ON', () => {});\n });\n\n return database;\n}\n\n/**\n * Builds a knex SQLite3 connection config\n *\n * @param dbConfig - The database config\n * @param overrides - Additional options to merge with the config\n */\nexport function buildSqliteDatabaseConfig(\n dbConfig: Config,\n overrides?: Knex.Config,\n): Knex.Config {\n const baseConfig = dbConfig.get<Knex.Config>();\n\n // Normalize config to always contain a connection object\n if (typeof baseConfig.connection === 'string') {\n baseConfig.connection = { filename: baseConfig.connection };\n }\n if (overrides && typeof overrides.connection === 'string') {\n overrides.connection = { filename: overrides.connection };\n }\n\n const config: Knex.Config = mergeDatabaseConfig(\n {\n connection: {},\n },\n baseConfig,\n {\n useNullAsDefault: true,\n },\n overrides,\n );\n\n return config;\n}\n\n/**\n * Provides a partial knex SQLite3 config to override database name.\n */\nexport function createSqliteNameOverride(name: string): Partial<Knex.Config> {\n return {\n connection: parseSqliteConnectionString(name),\n };\n}\n\n/**\n * Produces a partial knex SQLite3 connection config with database name.\n */\nexport function parseSqliteConnectionString(\n name: string,\n): Knex.Sqlite3ConnectionConfig {\n return {\n filename: name,\n };\n}\n\n/**\n * Provides a config lookup path for a plugin's config block.\n */\nfunction pluginPath(pluginId: string): string {\n return `plugin.${pluginId}`;\n}\n\nfunction normalizeConnection(\n connection: Knex.StaticConnectionConfig | JsonObject | string | undefined,\n): Partial<Knex.StaticConnectionConfig> {\n if (typeof connection === 'undefined' || connection === null) {\n return {};\n }\n\n return typeof connection === 'string' || connection instanceof String\n ? parseSqliteConnectionString(connection as string)\n : connection;\n}\n\nexport class Sqlite3Connector implements Connector {\n constructor(private readonly config: Config) {}\n\n async getClient(\n pluginId: string,\n deps: {\n logger: LoggerService;\n lifecycle: LifecycleService;\n },\n ): Promise<Knex> {\n const pluginConfig = new ConfigReader(\n this.getConfigForPlugin(pluginId) as JsonObject,\n );\n\n const pluginDivisionMode = this.getPluginDivisionModeConfig();\n if (pluginDivisionMode !== 'database') {\n throw new Error(\n `The SQLite driver does not support plugin division mode '${pluginDivisionMode}'`,\n );\n }\n\n const databaseClientOverrides = mergeDatabaseConfig(\n {},\n this.getDatabaseOverrides(pluginId),\n );\n\n const client = createSqliteDatabaseClient(\n pluginId,\n pluginConfig,\n deps,\n databaseClientOverrides,\n );\n\n return client;\n }\n\n /**\n * Provides the canonical database name for a given plugin.\n *\n * This method provides the effective database name which is determined using global\n * and plugin specific database config. If no explicit database name is configured\n * and `pluginDivisionMode` is not `schema`, this method will provide a generated name\n * which is the pluginId prefixed with 'backstage_plugin_'. If `pluginDivisionMode` is\n * `schema`, it will fallback to using the default database for the knex instance.\n *\n * @param pluginId - Lookup the database name for given plugin\n * @returns String representing the plugin's database name\n */\n private getDatabaseName(pluginId: string): string | undefined {\n const connection = this.getConnectionConfig(pluginId);\n\n const sqliteFilename: string | undefined = (\n connection as Knex.Sqlite3ConnectionConfig\n ).filename;\n\n if (sqliteFilename === ':memory:') {\n return sqliteFilename;\n }\n\n const sqliteDirectory =\n (connection as { directory?: string }).directory ?? '.';\n\n return path.join(sqliteDirectory, sqliteFilename ?? `${pluginId}.sqlite`);\n }\n\n /**\n * Provides the client type which should be used for a given plugin.\n *\n * The client type is determined by plugin specific config if present.\n * Otherwise the base client is used as the fallback.\n *\n * @param pluginId - Plugin to get the client type for\n * @returns Object with client type returned as `client` and boolean\n * representing whether or not the client was overridden as\n * `overridden`\n */\n private getClientType(pluginId: string): {\n client: string;\n overridden: boolean;\n } {\n const pluginClient = this.config.getOptionalString(\n `${pluginPath(pluginId)}.client`,\n );\n\n const baseClient = this.config.getString('client');\n const client = pluginClient ?? baseClient;\n return {\n client,\n overridden: client !== baseClient,\n };\n }\n\n private getRoleConfig(pluginId: string): string | undefined {\n return (\n this.config.getOptionalString(`${pluginPath(pluginId)}.role`) ??\n this.config.getOptionalString('role')\n );\n }\n\n /**\n * Provides the knexConfig which should be used for a given plugin.\n *\n * @param pluginId - Plugin to get the knexConfig for\n * @returns The merged knexConfig value or undefined if it isn't specified\n */\n private getAdditionalKnexConfig(pluginId: string): JsonObject | undefined {\n const pluginConfig = this.config\n .getOptionalConfig(`${pluginPath(pluginId)}.knexConfig`)\n ?.get<JsonObject>();\n\n const baseConfig = this.config\n .getOptionalConfig('knexConfig')\n ?.get<JsonObject>();\n\n return merge(baseConfig, pluginConfig);\n }\n\n private getPluginDivisionModeConfig(): string {\n return this.config.getOptionalString('pluginDivisionMode') ?? 'database';\n }\n\n /**\n * Provides a Knex connection plugin config by combining base and plugin\n * config.\n *\n * This method provides a baseConfig for a plugin database connector. If the\n * client type has not been overridden, the global connection config will be\n * included with plugin specific config as the base. Values from the plugin\n * connection take precedence over the base. Base database name is omitted for\n * all supported databases excluding SQLite unless `pluginDivisionMode` is set\n * to `schema`.\n */\n private getConnectionConfig(pluginId: string): Knex.StaticConnectionConfig {\n const { client, overridden } = this.getClientType(pluginId);\n\n let baseConnection = normalizeConnection(this.config.get('connection'));\n\n if (\n client.includes('sqlite3') &&\n 'filename' in baseConnection &&\n baseConnection.filename !== ':memory:'\n ) {\n throw new Error(\n '`connection.filename` is not supported for the base sqlite connection. Prefer `connection.directory` or provide a filename for the plugin connection instead.',\n );\n }\n\n // Databases cannot be shared unless the `pluginDivisionMode` is set to `schema`. The\n // `database` property from the base connection is omitted unless `pluginDivisionMode`\n // is set to `schema`. SQLite3's `filename` property is an exception as this is used as a\n // directory elsewhere so we preserve `filename`.\n if (this.getPluginDivisionModeConfig() !== 'schema') {\n baseConnection = omit(baseConnection, 'database');\n }\n\n // get and normalize optional plugin specific database connection\n const connection = normalizeConnection(\n this.config.getOptional(`${pluginPath(pluginId)}.connection`),\n );\n\n return {\n // include base connection if client type has not been overridden\n ...(overridden ? {} : baseConnection),\n ...connection,\n } as Knex.StaticConnectionConfig;\n }\n\n /**\n * Provides a Knex database config for a given plugin.\n *\n * This method provides a Knex configuration object along with the plugin's\n * client type.\n *\n * @param pluginId - The plugin that the database config should correspond with\n */\n private getConfigForPlugin(pluginId: string): Knex.Config {\n const { client } = this.getClientType(pluginId);\n const role = this.getRoleConfig(pluginId);\n\n return {\n ...this.getAdditionalKnexConfig(pluginId),\n client,\n connection: this.getConnectionConfig(pluginId),\n ...(role && { role }),\n };\n }\n\n /**\n * Provides a partial `Knex.Config`• database name override for a given plugin.\n *\n * @param pluginId - Target plugin to get database name override\n * @returns Partial `Knex.Config` with database name override\n */\n private getDatabaseOverrides(pluginId: string): Knex.Config {\n const databaseName = this.getDatabaseName(pluginId);\n return databaseName ? createSqliteNameOverride(databaseName) : {};\n }\n}\n"],"names":["path","ensureDirSync","DevDataStore","knexFactory","mergeDatabaseConfig","ConfigReader","merge","omit"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sqlite3.cjs.js","sources":["../../../../src/entrypoints/database/connectors/sqlite3.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { DevDataStore } from '@backstage/backend-dev-utils';\nimport { LifecycleService, LoggerService } from '@backstage/backend-plugin-api';\nimport { Config, ConfigReader } from '@backstage/config';\nimport { JsonObject } from '@backstage/types';\nimport { ensureDirSync } from 'fs-extra';\nimport knexFactory, { Knex } from 'knex';\nimport { merge, omit } from 'lodash';\nimport path from 'path';\nimport { Connector } from '../types';\nimport { mergeDatabaseConfig } from './mergeDatabaseConfig';\n\n/**\n * Creates a knex SQLite3 database connection\n *\n * @param dbConfig - The database config\n * @param overrides - Additional options to merge with the config\n */\nexport function createSqliteDatabaseClient(\n pluginId: string,\n dbConfig: Config,\n deps: {\n logger: LoggerService;\n lifecycle: LifecycleService;\n },\n overrides?: Knex.Config,\n) {\n const knexConfig = buildSqliteDatabaseConfig(dbConfig, overrides);\n const connConfig = knexConfig.connection as Knex.Sqlite3ConnectionConfig;\n\n const filename = connConfig.filename ?? ':memory:';\n\n // If storage on disk is used, ensure that the directory exists\n if (filename !== ':memory:') {\n const directory = path.dirname(filename);\n ensureDirSync(directory);\n }\n\n let database: Knex;\n\n if (deps && filename === ':memory:') {\n // The dev store is used during watch mode to store and restore the database\n // across reloads. It is only available when running the backend through\n // `backstage-cli package start`.\n const devStore = DevDataStore.get();\n\n if (devStore) {\n const dataKey = `sqlite3-db-${pluginId}`;\n\n const connectionLoader = async () => {\n // If seed data is available, use it tconnectionLoader restore the database\n const { data: seedData } = await devStore.load(dataKey);\n\n return {\n ...(knexConfig.connection as Knex.Sqlite3ConnectionConfig),\n filename: seedData ?? ':memory:',\n };\n };\n\n database = knexFactory({\n ...knexConfig,\n connection: Object.assign(connectionLoader, {\n // This is a workaround for the knex SQLite driver always warning when using a config loader\n filename: ':memory:',\n }),\n });\n\n // If the dev store is available we save the database state on shutdown\n deps.lifecycle.addShutdownHook(async () => {\n const connection = await database.client.acquireConnection();\n const data = connection.serialize();\n await devStore.save(dataKey, data);\n });\n } else {\n database = knexFactory(knexConfig);\n }\n } else {\n database = knexFactory(knexConfig);\n }\n\n database.client.pool.on('createSuccess', (_eventId: any, resource: any) => {\n resource.run('PRAGMA foreign_keys = ON', () => {});\n });\n\n return database;\n}\n\n/**\n * Builds a knex SQLite3 connection config\n *\n * @param dbConfig - The database config\n * @param overrides - Additional options to merge with the config\n */\nexport function buildSqliteDatabaseConfig(\n dbConfig: Config,\n overrides?: Knex.Config,\n): Knex.Config {\n const baseConfig = dbConfig.get<Knex.Config>();\n\n // Normalize config to always contain a connection object\n if (typeof baseConfig.connection === 'string') {\n baseConfig.connection = { filename: baseConfig.connection };\n }\n if (overrides && typeof overrides.connection === 'string') {\n overrides.connection = { filename: overrides.connection };\n }\n\n const config: Knex.Config = mergeDatabaseConfig(\n {\n connection: {},\n },\n baseConfig,\n {\n useNullAsDefault: true,\n },\n overrides,\n );\n\n return config;\n}\n\n/**\n * Provides a partial knex SQLite3 config to override database name.\n */\nexport function createSqliteNameOverride(name: string): Partial<Knex.Config> {\n return {\n connection: parseSqliteConnectionString(name),\n };\n}\n\n/**\n * Produces a partial knex SQLite3 connection config with database name.\n */\nexport function parseSqliteConnectionString(\n name: string,\n): Knex.Sqlite3ConnectionConfig {\n return {\n filename: name,\n };\n}\n\n/**\n * Provides a config lookup path for a plugin's config block.\n */\nfunction pluginPath(pluginId: string): string {\n return `plugin.${pluginId}`;\n}\n\nfunction normalizeConnection(\n connection: Knex.StaticConnectionConfig | JsonObject | string | undefined,\n): Partial<Knex.StaticConnectionConfig> {\n if (typeof connection === 'undefined' || connection === null) {\n return {};\n }\n\n return typeof connection === 'string' || connection instanceof String\n ? parseSqliteConnectionString(connection as string)\n : connection;\n}\n\nexport class Sqlite3Connector implements Connector {\n constructor(private readonly config: Config) {}\n\n async getClient(\n pluginId: string,\n deps: {\n logger: LoggerService;\n lifecycle: LifecycleService;\n },\n ): Promise<Knex> {\n const pluginConfig = new ConfigReader(\n this.getConfigForPlugin(pluginId) as JsonObject,\n );\n\n const pluginDivisionMode = this.getPluginDivisionModeConfig();\n if (pluginDivisionMode !== 'database') {\n throw new Error(\n `The SQLite driver does not support plugin division mode '${pluginDivisionMode}'`,\n );\n }\n\n const databaseClientOverrides = mergeDatabaseConfig(\n {},\n this.getDatabaseOverrides(pluginId),\n );\n\n const client = createSqliteDatabaseClient(\n pluginId,\n pluginConfig,\n deps,\n databaseClientOverrides,\n );\n\n return client;\n }\n\n /**\n * Provides the canonical database name for a given plugin.\n *\n * This method provides the effective database name which is determined using global\n * and plugin specific database config. If no explicit database name is configured\n * and `pluginDivisionMode` is not `schema`, this method will provide a generated name\n * which is the pluginId prefixed with 'backstage_plugin_'. If `pluginDivisionMode` is\n * `schema`, it will fallback to using the default database for the knex instance.\n *\n * @param pluginId - Lookup the database name for given plugin\n * @returns String representing the plugin's database name\n */\n private getDatabaseName(pluginId: string): string | undefined {\n const connection = this.getConnectionConfig(pluginId);\n\n const sqliteFilename: string | undefined = (\n connection as Knex.Sqlite3ConnectionConfig\n ).filename;\n\n if (sqliteFilename === ':memory:') {\n return sqliteFilename;\n }\n\n const sqliteDirectory =\n (connection as { directory?: string }).directory ?? '.';\n\n return path.join(sqliteDirectory, sqliteFilename ?? `${pluginId}.sqlite`);\n }\n\n /**\n * Provides the client type which should be used for a given plugin.\n *\n * The client type is determined by plugin specific config if present.\n * Otherwise the base client is used as the fallback.\n *\n * @param pluginId - Plugin to get the client type for\n * @returns Object with client type returned as `client` and boolean\n * representing whether or not the client was overridden as\n * `overridden`\n */\n private getClientType(pluginId: string): {\n client: string;\n overridden: boolean;\n } {\n const pluginClient = this.config.getOptionalString(\n `${pluginPath(pluginId)}.client`,\n );\n\n const baseClient = this.config.getString('client');\n const client = pluginClient ?? baseClient;\n return {\n client,\n overridden: client !== baseClient,\n };\n }\n\n private getRoleConfig(pluginId: string): string | undefined {\n return (\n this.config.getOptionalString(`${pluginPath(pluginId)}.role`) ??\n this.config.getOptionalString('role')\n );\n }\n\n /**\n * Provides the knexConfig which should be used for a given plugin.\n *\n * @param pluginId - Plugin to get the knexConfig for\n * @returns The merged knexConfig value or undefined if it isn't specified\n */\n private getAdditionalKnexConfig(pluginId: string): JsonObject | undefined {\n const pluginConfig = this.config\n .getOptionalConfig(`${pluginPath(pluginId)}.knexConfig`)\n ?.get<JsonObject>();\n\n const baseConfig = this.config\n .getOptionalConfig('knexConfig')\n ?.get<JsonObject>();\n\n return merge(baseConfig, pluginConfig);\n }\n\n private getPluginDivisionModeConfig(): string {\n return this.config.getOptionalString('pluginDivisionMode') ?? 'database';\n }\n\n /**\n * Provides a Knex connection plugin config by combining base and plugin\n * config.\n *\n * This method provides a baseConfig for a plugin database connector. If the\n * client type has not been overridden, the global connection config will be\n * included with plugin specific config as the base. Values from the plugin\n * connection take precedence over the base. Base database name is omitted for\n * all supported databases excluding SQLite unless `pluginDivisionMode` is set\n * to `schema`.\n */\n private getConnectionConfig(pluginId: string): Knex.StaticConnectionConfig {\n const { client, overridden } = this.getClientType(pluginId);\n\n let baseConnection = normalizeConnection(this.config.get('connection'));\n\n if (\n client.includes('sqlite3') &&\n 'filename' in baseConnection &&\n baseConnection.filename !== ':memory:'\n ) {\n throw new Error(\n '`connection.filename` is not supported for the base sqlite connection. Prefer `connection.directory` or provide a filename for the plugin connection instead.',\n );\n }\n\n // Databases cannot be shared unless the `pluginDivisionMode` is set to `schema`. The\n // `database` property from the base connection is omitted unless `pluginDivisionMode`\n // is set to `schema`. SQLite3's `filename` property is an exception as this is used as a\n // directory elsewhere so we preserve `filename`.\n if (this.getPluginDivisionModeConfig() !== 'schema') {\n baseConnection = omit(baseConnection, 'database');\n }\n\n // get and normalize optional plugin specific database connection\n const connection = normalizeConnection(\n this.config.getOptional(`${pluginPath(pluginId)}.connection`),\n );\n\n return {\n // include base connection if client type has not been overridden\n ...(overridden ? {} : baseConnection),\n ...connection,\n } as Knex.StaticConnectionConfig;\n }\n\n /**\n * Provides a Knex database config for a given plugin.\n *\n * This method provides a Knex configuration object along with the plugin's\n * client type.\n *\n * @param pluginId - The plugin that the database config should correspond with\n */\n private getConfigForPlugin(pluginId: string): Knex.Config {\n const { client } = this.getClientType(pluginId);\n const role = this.getRoleConfig(pluginId);\n\n return {\n ...this.getAdditionalKnexConfig(pluginId),\n client,\n connection: this.getConnectionConfig(pluginId),\n ...(role && { role }),\n };\n }\n\n /**\n * Provides a partial `Knex.Config`• database name override for a given plugin.\n *\n * @param pluginId - Target plugin to get database name override\n * @returns Partial `Knex.Config` with database name override\n */\n private getDatabaseOverrides(pluginId: string): Knex.Config {\n const databaseName = this.getDatabaseName(pluginId);\n return databaseName ? createSqliteNameOverride(databaseName) : {};\n }\n}\n"],"names":["path","ensureDirSync","DevDataStore","knexFactory","mergeDatabaseConfig","ConfigReader","merge","omit"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"databaseServiceFactory.cjs.js","sources":["../../../src/entrypoints/database/databaseServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createServiceFactory,\n} from '@backstage/backend-plugin-api';\nimport { ConfigReader } from '@backstage/config';\nimport { DatabaseManager } from './DatabaseManager';\n\n/**\n * Database access and management via `knex`.\n *\n * See {@link @backstage/code-plugin-api#DatabaseService}\n * and {@link https://backstage.io/docs/backend-system/core-services/database | the service docs}\n * for more information.\n *\n * @public\n */\nexport const databaseServiceFactory = createServiceFactory({\n service: coreServices.database,\n deps: {\n config: coreServices.rootConfig,\n lifecycle: coreServices.lifecycle,\n logger: coreServices.logger,\n pluginMetadata: coreServices.pluginMetadata,\n rootLifecycle: coreServices.rootLifecycle,\n rootLogger: coreServices.rootLogger,\n },\n async createRootContext({ config, rootLifecycle, rootLogger }) {\n return config.getOptional('backend.database')\n ? DatabaseManager.fromConfig(config, { rootLifecycle, rootLogger })\n : DatabaseManager.fromConfig(\n new ConfigReader({\n backend: {\n database: { client: 'better-sqlite3', connection: ':memory:' },\n },\n }),\n { rootLifecycle, rootLogger },\n );\n },\n async factory({ pluginMetadata, lifecycle, logger }, databaseManager) {\n return databaseManager.forPlugin(pluginMetadata.getId(), {\n lifecycle,\n logger,\n });\n },\n});\n"],"names":["createServiceFactory","coreServices","config","DatabaseManager","ConfigReader"],"mappings":";;;;;;AAgCO,MAAM,yBAAyBA,qCAAqB,CAAA;AAAA,EACzD,SAASC,6BAAa,CAAA,QAAA;AAAA,EACtB,IAAM,EAAA;AAAA,IACJ,QAAQA,6BAAa,CAAA,UAAA;AAAA,IACrB,WAAWA,6BAAa,CAAA,SAAA;AAAA,IACxB,QAAQA,6BAAa,CAAA,MAAA;AAAA,IACrB,gBAAgBA,6BAAa,CAAA,cAAA;AAAA,IAC7B,eAAeA,6BAAa,CAAA,aAAA;AAAA,IAC5B,YAAYA,6BAAa,CAAA
|
|
1
|
+
{"version":3,"file":"databaseServiceFactory.cjs.js","sources":["../../../src/entrypoints/database/databaseServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createServiceFactory,\n} from '@backstage/backend-plugin-api';\nimport { ConfigReader } from '@backstage/config';\nimport { DatabaseManager } from './DatabaseManager';\n\n/**\n * Database access and management via `knex`.\n *\n * See {@link @backstage/code-plugin-api#DatabaseService}\n * and {@link https://backstage.io/docs/backend-system/core-services/database | the service docs}\n * for more information.\n *\n * @public\n */\nexport const databaseServiceFactory = createServiceFactory({\n service: coreServices.database,\n deps: {\n config: coreServices.rootConfig,\n lifecycle: coreServices.lifecycle,\n logger: coreServices.logger,\n pluginMetadata: coreServices.pluginMetadata,\n rootLifecycle: coreServices.rootLifecycle,\n rootLogger: coreServices.rootLogger,\n },\n async createRootContext({ config, rootLifecycle, rootLogger }) {\n return config.getOptional('backend.database')\n ? DatabaseManager.fromConfig(config, { rootLifecycle, rootLogger })\n : DatabaseManager.fromConfig(\n new ConfigReader({\n backend: {\n database: { client: 'better-sqlite3', connection: ':memory:' },\n },\n }),\n { rootLifecycle, rootLogger },\n );\n },\n async factory({ pluginMetadata, lifecycle, logger }, databaseManager) {\n return databaseManager.forPlugin(pluginMetadata.getId(), {\n lifecycle,\n logger,\n });\n },\n});\n"],"names":["createServiceFactory","coreServices","config","DatabaseManager","ConfigReader"],"mappings":";;;;;;AAgCO,MAAM,yBAAyBA,qCAAqB,CAAA;AAAA,EACzD,SAASC,6BAAa,CAAA,QAAA;AAAA,EACtB,IAAM,EAAA;AAAA,IACJ,QAAQA,6BAAa,CAAA,UAAA;AAAA,IACrB,WAAWA,6BAAa,CAAA,SAAA;AAAA,IACxB,QAAQA,6BAAa,CAAA,MAAA;AAAA,IACrB,gBAAgBA,6BAAa,CAAA,cAAA;AAAA,IAC7B,eAAeA,6BAAa,CAAA,aAAA;AAAA,IAC5B,YAAYA,6BAAa,CAAA;AAAA,GAC3B;AAAA,EACA,MAAM,iBAAkB,CAAA,UAAEC,QAAQ,EAAA,aAAA,EAAe,YAAc,EAAA;AAC7D,IAAA,OAAOA,QAAO,CAAA,WAAA,CAAY,kBAAkB,CAAA,GACxCC,+BAAgB,CAAA,UAAA,CAAWD,QAAQ,EAAA,EAAE,aAAe,EAAA,UAAA,EAAY,CAAA,GAChEC,+BAAgB,CAAA,UAAA;AAAA,MACd,IAAIC,mBAAa,CAAA;AAAA,QACf,OAAS,EAAA;AAAA,UACP,QAAU,EAAA,EAAE,MAAQ,EAAA,gBAAA,EAAkB,YAAY,UAAW;AAAA;AAC/D,OACD,CAAA;AAAA,MACD,EAAE,eAAe,UAAW;AAAA,KAC9B;AAAA,GACN;AAAA,EACA,MAAM,OAAQ,CAAA,EAAE,gBAAgB,SAAW,EAAA,MAAA,IAAU,eAAiB,EAAA;AACpE,IAAA,OAAO,eAAgB,CAAA,SAAA,CAAU,cAAe,CAAA,KAAA,EAAS,EAAA;AAAA,MACvD,SAAA;AAAA,MACA;AAAA,KACD,CAAA;AAAA;AAEL,CAAC;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HostDiscovery.cjs.js","sources":["../../../src/entrypoints/discovery/HostDiscovery.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport {\n DiscoveryService,\n RootConfigService,\n} from '@backstage/backend-plugin-api';\nimport { readHttpServerOptions } from '../rootHttpRouter/http/config';\n\ntype Target = string | { internal: string; external: string };\n\n/**\n * HostDiscovery is a basic PluginEndpointDiscovery implementation\n * that can handle plugins that are hosted in a single or multiple deployments.\n *\n * The deployment may be scaled horizontally, as long as the external URL\n * is the same for all instances. However, internal URLs will always be\n * resolved to the same host, so there won't be any balancing of internal traffic.\n *\n * @public\n */\nexport class HostDiscovery implements DiscoveryService {\n /**\n * Creates a new HostDiscovery discovery instance by reading\n * from the `backend` config section, specifically the `.baseUrl` for\n * discovering the external URL, and the `.listen` and `.https` config\n * for the internal one.\n *\n * Can be overridden in config by providing a target and corresponding plugins in `discovery.endpoints`.\n * eg.\n *\n * ```yaml\n * discovery:\n * endpoints:\n * - target: https://internal.example.com/internal-catalog\n * plugins: [catalog]\n * - target: https://internal.example.com/secure/api/{{pluginId}}\n * plugins: [auth, permission]\n * - target:\n * internal: https://internal.example.com/search\n * external: https://example.com/search\n * plugins: [search]\n * ```\n *\n * The fixed base path is `/api`, meaning the default full internal\n * path for the `catalog` plugin will be `http://localhost:7007/api/catalog`.\n */\n static fromConfig(config: RootConfigService) {\n const basePath = '/api';\n const externalBaseUrl = config\n .getString('backend.baseUrl')\n .replace(/\\/+$/, '');\n\n const {\n listen: { host: listenHost = '::', port: listenPort },\n } = readHttpServerOptions(config.getConfig('backend'));\n const protocol = config.has('backend.https') ? 'https' : 'http';\n\n // Translate bind-all to localhost, and support IPv6\n let host = listenHost;\n if (host === '::' || host === '') {\n // We use localhost instead of ::1, since IPv6-compatible systems should default\n // to using IPv6 when they see localhost, but if the system doesn't support IPv6\n // things will still work.\n host = 'localhost';\n } else if (host === '0.0.0.0') {\n host = '127.0.0.1';\n }\n if (host.includes(':')) {\n host = `[${host}]`;\n }\n\n const internalBaseUrl = `${protocol}://${host}:${listenPort}`;\n\n return new HostDiscovery(\n internalBaseUrl + basePath,\n externalBaseUrl + basePath,\n config.getOptionalConfig('discovery'),\n );\n }\n\n private constructor(\n private readonly internalBaseUrl: string,\n private readonly externalBaseUrl: string,\n private readonly discoveryConfig: Config | undefined,\n ) {}\n\n private getTargetFromConfig(pluginId: string, type: 'internal' | 'external') {\n const endpoints = this.discoveryConfig?.getOptionalConfigArray('endpoints');\n\n const target = endpoints\n ?.find(endpoint => endpoint.getStringArray('plugins').includes(pluginId))\n ?.get<Target>('target');\n\n if (!target) {\n const baseUrl =\n type === 'external' ? this.externalBaseUrl : this.internalBaseUrl;\n\n return `${baseUrl}/${encodeURIComponent(pluginId)}`;\n }\n\n if (typeof target === 'string') {\n return target.replace(\n /\\{\\{\\s*pluginId\\s*\\}\\}/g,\n encodeURIComponent(pluginId),\n );\n }\n\n return target[type].replace(\n /\\{\\{\\s*pluginId\\s*\\}\\}/g,\n encodeURIComponent(pluginId),\n );\n }\n\n async getBaseUrl(pluginId: string): Promise<string> {\n return this.getTargetFromConfig(pluginId, 'internal');\n }\n\n async getExternalBaseUrl(pluginId: string): Promise<string> {\n return this.getTargetFromConfig(pluginId, 'external');\n }\n}\n"],"names":["config","readHttpServerOptions"],"mappings":";;;;AAmCO,MAAM,aAA0C,CAAA;AAAA,EA4D7C,WAAA,CACW,eACA,EAAA,eAAA,EACA,eACjB,EAAA;AAHiB,IAAA,IAAA,CAAA,eAAA,GAAA,eAAA
|
|
1
|
+
{"version":3,"file":"HostDiscovery.cjs.js","sources":["../../../src/entrypoints/discovery/HostDiscovery.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport {\n DiscoveryService,\n RootConfigService,\n} from '@backstage/backend-plugin-api';\nimport { readHttpServerOptions } from '../rootHttpRouter/http/config';\n\ntype Target = string | { internal: string; external: string };\n\n/**\n * HostDiscovery is a basic PluginEndpointDiscovery implementation\n * that can handle plugins that are hosted in a single or multiple deployments.\n *\n * The deployment may be scaled horizontally, as long as the external URL\n * is the same for all instances. However, internal URLs will always be\n * resolved to the same host, so there won't be any balancing of internal traffic.\n *\n * @public\n */\nexport class HostDiscovery implements DiscoveryService {\n /**\n * Creates a new HostDiscovery discovery instance by reading\n * from the `backend` config section, specifically the `.baseUrl` for\n * discovering the external URL, and the `.listen` and `.https` config\n * for the internal one.\n *\n * Can be overridden in config by providing a target and corresponding plugins in `discovery.endpoints`.\n * eg.\n *\n * ```yaml\n * discovery:\n * endpoints:\n * - target: https://internal.example.com/internal-catalog\n * plugins: [catalog]\n * - target: https://internal.example.com/secure/api/{{pluginId}}\n * plugins: [auth, permission]\n * - target:\n * internal: https://internal.example.com/search\n * external: https://example.com/search\n * plugins: [search]\n * ```\n *\n * The fixed base path is `/api`, meaning the default full internal\n * path for the `catalog` plugin will be `http://localhost:7007/api/catalog`.\n */\n static fromConfig(config: RootConfigService) {\n const basePath = '/api';\n const externalBaseUrl = config\n .getString('backend.baseUrl')\n .replace(/\\/+$/, '');\n\n const {\n listen: { host: listenHost = '::', port: listenPort },\n } = readHttpServerOptions(config.getConfig('backend'));\n const protocol = config.has('backend.https') ? 'https' : 'http';\n\n // Translate bind-all to localhost, and support IPv6\n let host = listenHost;\n if (host === '::' || host === '') {\n // We use localhost instead of ::1, since IPv6-compatible systems should default\n // to using IPv6 when they see localhost, but if the system doesn't support IPv6\n // things will still work.\n host = 'localhost';\n } else if (host === '0.0.0.0') {\n host = '127.0.0.1';\n }\n if (host.includes(':')) {\n host = `[${host}]`;\n }\n\n const internalBaseUrl = `${protocol}://${host}:${listenPort}`;\n\n return new HostDiscovery(\n internalBaseUrl + basePath,\n externalBaseUrl + basePath,\n config.getOptionalConfig('discovery'),\n );\n }\n\n private constructor(\n private readonly internalBaseUrl: string,\n private readonly externalBaseUrl: string,\n private readonly discoveryConfig: Config | undefined,\n ) {}\n\n private getTargetFromConfig(pluginId: string, type: 'internal' | 'external') {\n const endpoints = this.discoveryConfig?.getOptionalConfigArray('endpoints');\n\n const target = endpoints\n ?.find(endpoint => endpoint.getStringArray('plugins').includes(pluginId))\n ?.get<Target>('target');\n\n if (!target) {\n const baseUrl =\n type === 'external' ? this.externalBaseUrl : this.internalBaseUrl;\n\n return `${baseUrl}/${encodeURIComponent(pluginId)}`;\n }\n\n if (typeof target === 'string') {\n return target.replace(\n /\\{\\{\\s*pluginId\\s*\\}\\}/g,\n encodeURIComponent(pluginId),\n );\n }\n\n return target[type].replace(\n /\\{\\{\\s*pluginId\\s*\\}\\}/g,\n encodeURIComponent(pluginId),\n );\n }\n\n async getBaseUrl(pluginId: string): Promise<string> {\n return this.getTargetFromConfig(pluginId, 'internal');\n }\n\n async getExternalBaseUrl(pluginId: string): Promise<string> {\n return this.getTargetFromConfig(pluginId, 'external');\n }\n}\n"],"names":["config","readHttpServerOptions"],"mappings":";;;;AAmCO,MAAM,aAA0C,CAAA;AAAA,EA4D7C,WAAA,CACW,eACA,EAAA,eAAA,EACA,eACjB,EAAA;AAHiB,IAAA,IAAA,CAAA,eAAA,GAAA,eAAA;AACA,IAAA,IAAA,CAAA,eAAA,GAAA,eAAA;AACA,IAAA,IAAA,CAAA,eAAA,GAAA,eAAA;AAAA;AAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAtCH,OAAO,WAAWA,QAA2B,EAAA;AAC3C,IAAA,MAAM,QAAW,GAAA,MAAA;AACjB,IAAA,MAAM,kBAAkBA,QACrB,CAAA,SAAA,CAAU,iBAAiB,CAC3B,CAAA,OAAA,CAAQ,QAAQ,EAAE,CAAA;AAErB,IAAM,MAAA;AAAA,MACJ,QAAQ,EAAE,IAAA,EAAM,UAAa,GAAA,IAAA,EAAM,MAAM,UAAW;AAAA,KAClD,GAAAC,4BAAA,CAAsBD,QAAO,CAAA,SAAA,CAAU,SAAS,CAAC,CAAA;AACrD,IAAA,MAAM,QAAW,GAAAA,QAAA,CAAO,GAAI,CAAA,eAAe,IAAI,OAAU,GAAA,MAAA;AAGzD,IAAA,IAAI,IAAO,GAAA,UAAA;AACX,IAAI,IAAA,IAAA,KAAS,IAAQ,IAAA,IAAA,KAAS,EAAI,EAAA;AAIhC,MAAO,IAAA,GAAA,WAAA;AAAA,KACT,MAAA,IAAW,SAAS,SAAW,EAAA;AAC7B,MAAO,IAAA,GAAA,WAAA;AAAA;AAET,IAAI,IAAA,IAAA,CAAK,QAAS,CAAA,GAAG,CAAG,EAAA;AACtB,MAAA,IAAA,GAAO,IAAI,IAAI,CAAA,CAAA,CAAA;AAAA;AAGjB,IAAA,MAAM,kBAAkB,CAAG,EAAA,QAAQ,CAAM,GAAA,EAAA,IAAI,IAAI,UAAU,CAAA,CAAA;AAE3D,IAAA,OAAO,IAAI,aAAA;AAAA,MACT,eAAkB,GAAA,QAAA;AAAA,MAClB,eAAkB,GAAA,QAAA;AAAA,MAClBA,QAAA,CAAO,kBAAkB,WAAW;AAAA,KACtC;AAAA;AACF,EAQQ,mBAAA,CAAoB,UAAkB,IAA+B,EAAA;AAC3E,IAAA,MAAM,SAAY,GAAA,IAAA,CAAK,eAAiB,EAAA,sBAAA,CAAuB,WAAW,CAAA;AAE1E,IAAA,MAAM,MAAS,GAAA,SAAA,EACX,IAAK,CAAA,CAAA,QAAA,KAAY,QAAS,CAAA,cAAA,CAAe,SAAS,CAAA,CAAE,QAAS,CAAA,QAAQ,CAAC,CAAA,EACtE,IAAY,QAAQ,CAAA;AAExB,IAAA,IAAI,CAAC,MAAQ,EAAA;AACX,MAAA,MAAM,OACJ,GAAA,IAAA,KAAS,UAAa,GAAA,IAAA,CAAK,kBAAkB,IAAK,CAAA,eAAA;AAEpD,MAAA,OAAO,CAAG,EAAA,OAAO,CAAI,CAAA,EAAA,kBAAA,CAAmB,QAAQ,CAAC,CAAA,CAAA;AAAA;AAGnD,IAAI,IAAA,OAAO,WAAW,QAAU,EAAA;AAC9B,MAAA,OAAO,MAAO,CAAA,OAAA;AAAA,QACZ,yBAAA;AAAA,QACA,mBAAmB,QAAQ;AAAA,OAC7B;AAAA;AAGF,IAAO,OAAA,MAAA,CAAO,IAAI,CAAE,CAAA,OAAA;AAAA,MAClB,yBAAA;AAAA,MACA,mBAAmB,QAAQ;AAAA,KAC7B;AAAA;AACF,EAEA,MAAM,WAAW,QAAmC,EAAA;AAClD,IAAO,OAAA,IAAA,CAAK,mBAAoB,CAAA,QAAA,EAAU,UAAU,CAAA;AAAA;AACtD,EAEA,MAAM,mBAAmB,QAAmC,EAAA;AAC1D,IAAO,OAAA,IAAA,CAAK,mBAAoB,CAAA,QAAA,EAAU,UAAU,CAAA;AAAA;AAExD;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discoveryServiceFactory.cjs.js","sources":["../../../src/entrypoints/discovery/discoveryServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createServiceFactory,\n} from '@backstage/backend-plugin-api';\nimport { HostDiscovery } from './HostDiscovery';\n\n/**\n * Service discovery for inter-plugin communication.\n *\n * See {@link @backstage/code-plugin-api#DiscoveryService}\n * and {@link https://backstage.io/docs/backend-system/core-services/discovery | the service docs}\n * for more information.\n *\n * @public\n */\nexport const discoveryServiceFactory = createServiceFactory({\n service: coreServices.discovery,\n deps: {\n config: coreServices.rootConfig,\n },\n async factory({ config }) {\n return HostDiscovery.fromConfig(config);\n },\n});\n"],"names":["createServiceFactory","coreServices","HostDiscovery"],"mappings":";;;;;AA+BO,MAAM,0BAA0BA,qCAAqB,CAAA;AAAA,EAC1D,SAASC,6BAAa,CAAA,SAAA;AAAA,EACtB,IAAM,EAAA;AAAA,IACJ,QAAQA,6BAAa,CAAA
|
|
1
|
+
{"version":3,"file":"discoveryServiceFactory.cjs.js","sources":["../../../src/entrypoints/discovery/discoveryServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createServiceFactory,\n} from '@backstage/backend-plugin-api';\nimport { HostDiscovery } from './HostDiscovery';\n\n/**\n * Service discovery for inter-plugin communication.\n *\n * See {@link @backstage/code-plugin-api#DiscoveryService}\n * and {@link https://backstage.io/docs/backend-system/core-services/discovery | the service docs}\n * for more information.\n *\n * @public\n */\nexport const discoveryServiceFactory = createServiceFactory({\n service: coreServices.discovery,\n deps: {\n config: coreServices.rootConfig,\n },\n async factory({ config }) {\n return HostDiscovery.fromConfig(config);\n },\n});\n"],"names":["createServiceFactory","coreServices","HostDiscovery"],"mappings":";;;;;AA+BO,MAAM,0BAA0BA,qCAAqB,CAAA;AAAA,EAC1D,SAASC,6BAAa,CAAA,SAAA;AAAA,EACtB,IAAM,EAAA;AAAA,IACJ,QAAQA,6BAAa,CAAA;AAAA,GACvB;AAAA,EACA,MAAM,OAAA,CAAQ,EAAE,MAAA,EAAU,EAAA;AACxB,IAAO,OAAAC,2BAAA,CAAc,WAAW,MAAM,CAAA;AAAA;AAE1C,CAAC;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"httpAuthServiceFactory.cjs.js","sources":["../../../src/entrypoints/httpAuth/httpAuthServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AuthService,\n BackstageCredentials,\n BackstagePrincipalTypes,\n BackstageUserPrincipal,\n DiscoveryService,\n HttpAuthService,\n coreServices,\n createServiceFactory,\n} from '@backstage/backend-plugin-api';\nimport { AuthenticationError, NotAllowedError } from '@backstage/errors';\nimport { parse as parseCookie } from 'cookie';\nimport { Request, Response } from 'express';\n\nconst FIVE_MINUTES_MS = 5 * 60 * 1000;\n\nconst BACKSTAGE_AUTH_COOKIE = 'backstage-auth';\n\nfunction getTokenFromRequest(req: Request) {\n // TODO: support multiple auth headers (iterate rawHeaders)\n const authHeader = req.headers.authorization;\n if (typeof authHeader === 'string') {\n const matches = authHeader.match(/^Bearer[ ]+(\\S+)$/i);\n const token = matches?.[1];\n if (token) {\n return token;\n }\n }\n\n return undefined;\n}\n\nfunction getCookieFromRequest(req: Request) {\n const cookieHeader = req.headers.cookie;\n if (cookieHeader) {\n const cookies = parseCookie(cookieHeader);\n const token = cookies[BACKSTAGE_AUTH_COOKIE];\n if (token) {\n return token;\n }\n }\n\n return undefined;\n}\n\nfunction willExpireSoon(expiresAt: Date) {\n return Date.now() + FIVE_MINUTES_MS > expiresAt.getTime();\n}\n\nconst credentialsSymbol = Symbol('backstage-credentials');\nconst limitedCredentialsSymbol = Symbol('backstage-limited-credentials');\n\ntype RequestWithCredentials = Request & {\n [credentialsSymbol]?: Promise<BackstageCredentials>;\n [limitedCredentialsSymbol]?: Promise<BackstageCredentials>;\n};\n\nclass DefaultHttpAuthService implements HttpAuthService {\n readonly #auth: AuthService;\n readonly #discovery: DiscoveryService;\n readonly #pluginId: string;\n\n constructor(\n auth: AuthService,\n discovery: DiscoveryService,\n pluginId: string,\n ) {\n this.#auth = auth;\n this.#discovery = discovery;\n this.#pluginId = pluginId;\n }\n\n async #extractCredentialsFromRequest(req: Request) {\n const token = getTokenFromRequest(req);\n if (!token) {\n return await this.#auth.getNoneCredentials();\n }\n\n return await this.#auth.authenticate(token);\n }\n\n async #extractLimitedCredentialsFromRequest(req: Request) {\n const token = getTokenFromRequest(req);\n if (token) {\n return await this.#auth.authenticate(token, {\n allowLimitedAccess: true,\n });\n }\n\n const cookie = getCookieFromRequest(req);\n if (cookie) {\n return await this.#auth.authenticate(cookie, {\n allowLimitedAccess: true,\n });\n }\n\n return await this.#auth.getNoneCredentials();\n }\n\n async #getCredentials(req: RequestWithCredentials) {\n return (req[credentialsSymbol] ??=\n this.#extractCredentialsFromRequest(req));\n }\n\n async #getLimitedCredentials(req: RequestWithCredentials) {\n return (req[limitedCredentialsSymbol] ??=\n this.#extractLimitedCredentialsFromRequest(req));\n }\n\n async credentials<TAllowed extends keyof BackstagePrincipalTypes = 'unknown'>(\n req: Request,\n options?: {\n allow?: Array<TAllowed>;\n allowLimitedAccess?: boolean;\n },\n ): Promise<BackstageCredentials<BackstagePrincipalTypes[TAllowed]>> {\n // Limited and full credentials are treated as two separate cases, this lets\n // us avoid internal dependencies between the AuthService and\n // HttpAuthService implementations\n const credentials = options?.allowLimitedAccess\n ? await this.#getLimitedCredentials(req)\n : await this.#getCredentials(req);\n\n const allowed = options?.allow;\n if (!allowed) {\n return credentials as any;\n }\n\n if (this.#auth.isPrincipal(credentials, 'none')) {\n if (allowed.includes('none' as TAllowed)) {\n return credentials as any;\n }\n\n throw new AuthenticationError('Missing credentials');\n } else if (this.#auth.isPrincipal(credentials, 'user')) {\n if (allowed.includes('user' as TAllowed)) {\n return credentials as any;\n }\n\n throw new NotAllowedError(\n `This endpoint does not allow 'user' credentials`,\n );\n } else if (this.#auth.isPrincipal(credentials, 'service')) {\n if (allowed.includes('service' as TAllowed)) {\n return credentials as any;\n }\n\n throw new NotAllowedError(\n `This endpoint does not allow 'service' credentials`,\n );\n }\n\n throw new NotAllowedError(\n 'Unknown principal type, this should never happen',\n );\n }\n\n async issueUserCookie(\n res: Response,\n options?: { credentials?: BackstageCredentials },\n ): Promise<{ expiresAt: Date }> {\n if (res.headersSent) {\n throw new Error('Failed to issue user cookie, headers were already sent');\n }\n\n let credentials: BackstageCredentials<BackstageUserPrincipal>;\n if (options?.credentials) {\n if (this.#auth.isPrincipal(options.credentials, 'none')) {\n res.clearCookie(\n BACKSTAGE_AUTH_COOKIE,\n await this.#getCookieOptions(res.req),\n );\n return { expiresAt: new Date() };\n }\n if (!this.#auth.isPrincipal(options.credentials, 'user')) {\n throw new AuthenticationError(\n 'Refused to issue cookie for non-user principal',\n );\n }\n credentials = options.credentials;\n } else {\n credentials = await this.credentials(res.req, { allow: ['user'] });\n }\n\n const existingExpiresAt = await this.#existingCookieExpiration(res.req);\n if (existingExpiresAt && !willExpireSoon(existingExpiresAt)) {\n return { expiresAt: existingExpiresAt };\n }\n\n const { token, expiresAt } = await this.#auth.getLimitedUserToken(\n credentials,\n );\n if (!token) {\n throw new Error('User credentials is unexpectedly missing token');\n }\n\n res.cookie(BACKSTAGE_AUTH_COOKIE, token, {\n ...(await this.#getCookieOptions(res.req)),\n expires: expiresAt,\n });\n\n return { expiresAt };\n }\n\n async #getCookieOptions(_req: Request): Promise<{\n domain: string;\n httpOnly: true;\n secure: boolean;\n priority: 'high';\n sameSite: 'none' | 'lax';\n }> {\n // TODO: eventually we should read from `${req.protocol}://${req.hostname}`\n // once https://github.com/backstage/backstage/issues/24169 has landed\n const externalBaseUrlStr = await this.#discovery.getExternalBaseUrl(\n this.#pluginId,\n );\n const externalBaseUrl = new URL(externalBaseUrlStr);\n\n const secure =\n externalBaseUrl.protocol === 'https:' ||\n externalBaseUrl.hostname === 'localhost';\n\n return {\n domain: externalBaseUrl.hostname,\n httpOnly: true,\n secure,\n priority: 'high',\n sameSite: secure ? 'none' : 'lax',\n };\n }\n\n async #existingCookieExpiration(req: Request): Promise<Date | undefined> {\n const existingCookie = getCookieFromRequest(req);\n if (!existingCookie) {\n return undefined;\n }\n\n try {\n const existingCredentials = await this.#auth.authenticate(\n existingCookie,\n {\n allowLimitedAccess: true,\n },\n );\n if (!this.#auth.isPrincipal(existingCredentials, 'user')) {\n return undefined;\n }\n\n return existingCredentials.expiresAt;\n } catch (error) {\n if (error.name === 'AuthenticationError') {\n return undefined;\n }\n throw error;\n }\n }\n}\n\n/**\n * Authentication of HTTP requests.\n *\n * See {@link @backstage/code-plugin-api#HttpAuthService}\n * and {@link https://backstage.io/docs/backend-system/core-services/http-auth | the service docs}\n * for more information.\n *\n * @public\n */\nexport const httpAuthServiceFactory = createServiceFactory({\n service: coreServices.httpAuth,\n deps: {\n auth: coreServices.auth,\n discovery: coreServices.discovery,\n plugin: coreServices.pluginMetadata,\n },\n async factory({ auth, discovery, plugin }) {\n return new DefaultHttpAuthService(auth, discovery, plugin.getId());\n },\n});\n"],"names":["parseCookie","AuthenticationError","NotAllowedError","createServiceFactory","coreServices"],"mappings":";;;;;;AA8BA,MAAM,eAAA,GAAkB,IAAI,EAAK,GAAA,GAAA,CAAA;AAEjC,MAAM,qBAAwB,GAAA,gBAAA,CAAA;AAE9B,SAAS,oBAAoB,GAAc,EAAA;AAEzC,EAAM,MAAA,UAAA,GAAa,IAAI,OAAQ,CAAA,aAAA,CAAA;AAC/B,EAAI,IAAA,OAAO,eAAe,QAAU,EAAA;AAClC,IAAM,MAAA,OAAA,GAAU,UAAW,CAAA,KAAA,CAAM,oBAAoB,CAAA,CAAA;AACrD,IAAM,MAAA,KAAA,GAAQ,UAAU,CAAC,CAAA,CAAA;AACzB,IAAA,IAAI,KAAO,EAAA;AACT,MAAO,OAAA,KAAA,CAAA;AAAA,KACT;AAAA,GACF;AAEA,EAAO,OAAA,KAAA,CAAA,CAAA;AACT,CAAA;AAEA,SAAS,qBAAqB,GAAc,EAAA;AAC1C,EAAM,MAAA,YAAA,GAAe,IAAI,OAAQ,CAAA,MAAA,CAAA;AACjC,EAAA,IAAI,YAAc,EAAA;AAChB,IAAM,MAAA,OAAA,GAAUA,aAAY,YAAY,CAAA,CAAA;AACxC,IAAM,MAAA,KAAA,GAAQ,QAAQ,qBAAqB,CAAA,CAAA;AAC3C,IAAA,IAAI,KAAO,EAAA;AACT,MAAO,OAAA,KAAA,CAAA;AAAA,KACT;AAAA,GACF;AAEA,EAAO,OAAA,KAAA,CAAA,CAAA;AACT,CAAA;AAEA,SAAS,eAAe,SAAiB,EAAA;AACvC,EAAA,OAAO,IAAK,CAAA,GAAA,EAAQ,GAAA,eAAA,GAAkB,UAAU,OAAQ,EAAA,CAAA;AAC1D,CAAA;AAEA,MAAM,iBAAA,GAAoB,OAAO,uBAAuB,CAAA,CAAA;AACxD,MAAM,wBAAA,GAA2B,OAAO,+BAA+B,CAAA,CAAA;AAOvE,MAAM,sBAAkD,CAAA;AAAA,EAC7C,KAAA,CAAA;AAAA,EACA,UAAA,CAAA;AAAA,EACA,SAAA,CAAA;AAAA,EAET,WAAA,CACE,IACA,EAAA,SAAA,EACA,QACA,EAAA;AACA,IAAA,IAAA,CAAK,KAAQ,GAAA,IAAA,CAAA;AACb,IAAA,IAAA,CAAK,UAAa,GAAA,SAAA,CAAA;AAClB,IAAA,IAAA,CAAK,SAAY,GAAA,QAAA,CAAA;AAAA,GACnB;AAAA,EAEA,MAAM,+BAA+B,GAAc,EAAA;AACjD,IAAM,MAAA,KAAA,GAAQ,oBAAoB,GAAG,CAAA,CAAA;AACrC,IAAA,IAAI,CAAC,KAAO,EAAA;AACV,MAAO,OAAA,MAAM,IAAK,CAAA,KAAA,CAAM,kBAAmB,EAAA,CAAA;AAAA,KAC7C;AAEA,IAAA,OAAO,MAAM,IAAA,CAAK,KAAM,CAAA,YAAA,CAAa,KAAK,CAAA,CAAA;AAAA,GAC5C;AAAA,EAEA,MAAM,sCAAsC,GAAc,EAAA;AACxD,IAAM,MAAA,KAAA,GAAQ,oBAAoB,GAAG,CAAA,CAAA;AACrC,IAAA,IAAI,KAAO,EAAA;AACT,MAAA,OAAO,MAAM,IAAA,CAAK,KAAM,CAAA,YAAA,CAAa,KAAO,EAAA;AAAA,QAC1C,kBAAoB,EAAA,IAAA;AAAA,OACrB,CAAA,CAAA;AAAA,KACH;AAEA,IAAM,MAAA,MAAA,GAAS,qBAAqB,GAAG,CAAA,CAAA;AACvC,IAAA,IAAI,MAAQ,EAAA;AACV,MAAA,OAAO,MAAM,IAAA,CAAK,KAAM,CAAA,YAAA,CAAa,MAAQ,EAAA;AAAA,QAC3C,kBAAoB,EAAA,IAAA;AAAA,OACrB,CAAA,CAAA;AAAA,KACH;AAEA,IAAO,OAAA,MAAM,IAAK,CAAA,KAAA,CAAM,kBAAmB,EAAA,CAAA;AAAA,GAC7C;AAAA,EAEA,MAAM,gBAAgB,GAA6B,EAAA;AACjD,IAAA,OAAQ,GAAI,CAAA,iBAAiB,CAC3B,KAAA,IAAA,CAAK,+BAA+B,GAAG,CAAA,CAAA;AAAA,GAC3C;AAAA,EAEA,MAAM,uBAAuB,GAA6B,EAAA;AACxD,IAAA,OAAQ,GAAI,CAAA,wBAAwB,CAClC,KAAA,IAAA,CAAK,sCAAsC,GAAG,CAAA,CAAA;AAAA,GAClD;AAAA,EAEA,MAAM,WACJ,CAAA,GAAA,EACA,OAIkE,EAAA;AAIlE,IAAM,MAAA,WAAA,GAAc,OAAS,EAAA,kBAAA,GACzB,MAAM,IAAA,CAAK,sBAAuB,CAAA,GAAG,CACrC,GAAA,MAAM,IAAK,CAAA,eAAA,CAAgB,GAAG,CAAA,CAAA;AAElC,IAAA,MAAM,UAAU,OAAS,EAAA,KAAA,CAAA;AACzB,IAAA,IAAI,CAAC,OAAS,EAAA;AACZ,MAAO,OAAA,WAAA,CAAA;AAAA,KACT;AAEA,IAAA,IAAI,IAAK,CAAA,KAAA,CAAM,WAAY,CAAA,WAAA,EAAa,MAAM,CAAG,EAAA;AAC/C,MAAI,IAAA,OAAA,CAAQ,QAAS,CAAA,MAAkB,CAAG,EAAA;AACxC,QAAO,OAAA,WAAA,CAAA;AAAA,OACT;AAEA,MAAM,MAAA,IAAIC,2BAAoB,qBAAqB,CAAA,CAAA;AAAA,eAC1C,IAAK,CAAA,KAAA,CAAM,WAAY,CAAA,WAAA,EAAa,MAAM,CAAG,EAAA;AACtD,MAAI,IAAA,OAAA,CAAQ,QAAS,CAAA,MAAkB,CAAG,EAAA;AACxC,QAAO,OAAA,WAAA,CAAA;AAAA,OACT;AAEA,MAAA,MAAM,IAAIC,sBAAA;AAAA,QACR,CAAA,+CAAA,CAAA;AAAA,OACF,CAAA;AAAA,eACS,IAAK,CAAA,KAAA,CAAM,WAAY,CAAA,WAAA,EAAa,SAAS,CAAG,EAAA;AACzD,MAAI,IAAA,OAAA,CAAQ,QAAS,CAAA,SAAqB,CAAG,EAAA;AAC3C,QAAO,OAAA,WAAA,CAAA;AAAA,OACT;AAEA,MAAA,MAAM,IAAIA,sBAAA;AAAA,QACR,CAAA,kDAAA,CAAA;AAAA,OACF,CAAA;AAAA,KACF;AAEA,IAAA,MAAM,IAAIA,sBAAA;AAAA,MACR,kDAAA;AAAA,KACF,CAAA;AAAA,GACF;AAAA,EAEA,MAAM,eACJ,CAAA,GAAA,EACA,OAC8B,EAAA;AAC9B,IAAA,IAAI,IAAI,WAAa,EAAA;AACnB,MAAM,MAAA,IAAI,MAAM,wDAAwD,CAAA,CAAA;AAAA,KAC1E;AAEA,IAAI,IAAA,WAAA,CAAA;AACJ,IAAA,IAAI,SAAS,WAAa,EAAA;AACxB,MAAA,IAAI,KAAK,KAAM,CAAA,WAAA,CAAY,OAAQ,CAAA,WAAA,EAAa,MAAM,CAAG,EAAA;AACvD,QAAI,GAAA,CAAA,WAAA;AAAA,UACF,qBAAA;AAAA,UACA,MAAM,IAAA,CAAK,iBAAkB,CAAA,GAAA,CAAI,GAAG,CAAA;AAAA,SACtC,CAAA;AACA,QAAA,OAAO,EAAE,SAAA,kBAAe,IAAA,IAAA,EAAO,EAAA,CAAA;AAAA,OACjC;AACA,MAAA,IAAI,CAAC,IAAK,CAAA,KAAA,CAAM,YAAY,OAAQ,CAAA,WAAA,EAAa,MAAM,CAAG,EAAA;AACxD,QAAA,MAAM,IAAID,0BAAA;AAAA,UACR,gDAAA;AAAA,SACF,CAAA;AAAA,OACF;AACA,MAAA,WAAA,GAAc,OAAQ,CAAA,WAAA,CAAA;AAAA,KACjB,MAAA;AACL,MAAc,WAAA,GAAA,MAAM,IAAK,CAAA,WAAA,CAAY,GAAI,CAAA,GAAA,EAAK,EAAE,KAAO,EAAA,CAAC,MAAM,CAAA,EAAG,CAAA,CAAA;AAAA,KACnE;AAEA,IAAA,MAAM,iBAAoB,GAAA,MAAM,IAAK,CAAA,yBAAA,CAA0B,IAAI,GAAG,CAAA,CAAA;AACtE,IAAA,IAAI,iBAAqB,IAAA,CAAC,cAAe,CAAA,iBAAiB,CAAG,EAAA;AAC3D,MAAO,OAAA,EAAE,WAAW,iBAAkB,EAAA,CAAA;AAAA,KACxC;AAEA,IAAA,MAAM,EAAE,KAAO,EAAA,SAAA,EAAc,GAAA,MAAM,KAAK,KAAM,CAAA,mBAAA;AAAA,MAC5C,WAAA;AAAA,KACF,CAAA;AACA,IAAA,IAAI,CAAC,KAAO,EAAA;AACV,MAAM,MAAA,IAAI,MAAM,gDAAgD,CAAA,CAAA;AAAA,KAClE;AAEA,IAAI,GAAA,CAAA,MAAA,CAAO,uBAAuB,KAAO,EAAA;AAAA,MACvC,GAAI,MAAM,IAAK,CAAA,iBAAA,CAAkB,IAAI,GAAG,CAAA;AAAA,MACxC,OAAS,EAAA,SAAA;AAAA,KACV,CAAA,CAAA;AAED,IAAA,OAAO,EAAE,SAAU,EAAA,CAAA;AAAA,GACrB;AAAA,EAEA,MAAM,kBAAkB,IAMrB,EAAA;AAGD,IAAM,MAAA,kBAAA,GAAqB,MAAM,IAAA,CAAK,UAAW,CAAA,kBAAA;AAAA,MAC/C,IAAK,CAAA,SAAA;AAAA,KACP,CAAA;AACA,IAAM,MAAA,eAAA,GAAkB,IAAI,GAAA,CAAI,kBAAkB,CAAA,CAAA;AAElD,IAAA,MAAM,MACJ,GAAA,eAAA,CAAgB,QAAa,KAAA,QAAA,IAC7B,gBAAgB,QAAa,KAAA,WAAA,CAAA;AAE/B,IAAO,OAAA;AAAA,MACL,QAAQ,eAAgB,CAAA,QAAA;AAAA,MACxB,QAAU,EAAA,IAAA;AAAA,MACV,MAAA;AAAA,MACA,QAAU,EAAA,MAAA;AAAA,MACV,QAAA,EAAU,SAAS,MAAS,GAAA,KAAA;AAAA,KAC9B,CAAA;AAAA,GACF;AAAA,EAEA,MAAM,0BAA0B,GAAyC,EAAA;AACvE,IAAM,MAAA,cAAA,GAAiB,qBAAqB,GAAG,CAAA,CAAA;AAC/C,IAAA,IAAI,CAAC,cAAgB,EAAA;AACnB,MAAO,OAAA,KAAA,CAAA,CAAA;AAAA,KACT;AAEA,IAAI,IAAA;AACF,MAAM,MAAA,mBAAA,GAAsB,MAAM,IAAA,CAAK,KAAM,CAAA,YAAA;AAAA,QAC3C,cAAA;AAAA,QACA;AAAA,UACE,kBAAoB,EAAA,IAAA;AAAA,SACtB;AAAA,OACF,CAAA;AACA,MAAA,IAAI,CAAC,IAAK,CAAA,KAAA,CAAM,WAAY,CAAA,mBAAA,EAAqB,MAAM,CAAG,EAAA;AACxD,QAAO,OAAA,KAAA,CAAA,CAAA;AAAA,OACT;AAEA,MAAA,OAAO,mBAAoB,CAAA,SAAA,CAAA;AAAA,aACpB,KAAO,EAAA;AACd,MAAI,IAAA,KAAA,CAAM,SAAS,qBAAuB,EAAA;AACxC,QAAO,OAAA,KAAA,CAAA,CAAA;AAAA,OACT;AACA,MAAM,MAAA,KAAA,CAAA;AAAA,KACR;AAAA,GACF;AACF,CAAA;AAWO,MAAM,yBAAyBE,qCAAqB,CAAA;AAAA,EACzD,SAASC,6BAAa,CAAA,QAAA;AAAA,EACtB,IAAM,EAAA;AAAA,IACJ,MAAMA,6BAAa,CAAA,IAAA;AAAA,IACnB,WAAWA,6BAAa,CAAA,SAAA;AAAA,IACxB,QAAQA,6BAAa,CAAA,cAAA;AAAA,GACvB;AAAA,EACA,MAAM,OAAQ,CAAA,EAAE,IAAM,EAAA,SAAA,EAAW,QAAU,EAAA;AACzC,IAAA,OAAO,IAAI,sBAAuB,CAAA,IAAA,EAAM,SAAW,EAAA,MAAA,CAAO,OAAO,CAAA,CAAA;AAAA,GACnE;AACF,CAAC;;;;"}
|
|
1
|
+
{"version":3,"file":"httpAuthServiceFactory.cjs.js","sources":["../../../src/entrypoints/httpAuth/httpAuthServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AuthService,\n BackstageCredentials,\n BackstagePrincipalTypes,\n BackstageUserPrincipal,\n DiscoveryService,\n HttpAuthService,\n coreServices,\n createServiceFactory,\n} from '@backstage/backend-plugin-api';\nimport { AuthenticationError, NotAllowedError } from '@backstage/errors';\nimport { parse as parseCookie } from 'cookie';\nimport { Request, Response } from 'express';\n\nconst FIVE_MINUTES_MS = 5 * 60 * 1000;\n\nconst BACKSTAGE_AUTH_COOKIE = 'backstage-auth';\n\nfunction getTokenFromRequest(req: Request) {\n // TODO: support multiple auth headers (iterate rawHeaders)\n const authHeader = req.headers.authorization;\n if (typeof authHeader === 'string') {\n const matches = authHeader.match(/^Bearer[ ]+(\\S+)$/i);\n const token = matches?.[1];\n if (token) {\n return token;\n }\n }\n\n return undefined;\n}\n\nfunction getCookieFromRequest(req: Request) {\n const cookieHeader = req.headers.cookie;\n if (cookieHeader) {\n const cookies = parseCookie(cookieHeader);\n const token = cookies[BACKSTAGE_AUTH_COOKIE];\n if (token) {\n return token;\n }\n }\n\n return undefined;\n}\n\nfunction willExpireSoon(expiresAt: Date) {\n return Date.now() + FIVE_MINUTES_MS > expiresAt.getTime();\n}\n\nconst credentialsSymbol = Symbol('backstage-credentials');\nconst limitedCredentialsSymbol = Symbol('backstage-limited-credentials');\n\ntype RequestWithCredentials = Request & {\n [credentialsSymbol]?: Promise<BackstageCredentials>;\n [limitedCredentialsSymbol]?: Promise<BackstageCredentials>;\n};\n\nclass DefaultHttpAuthService implements HttpAuthService {\n readonly #auth: AuthService;\n readonly #discovery: DiscoveryService;\n readonly #pluginId: string;\n\n constructor(\n auth: AuthService,\n discovery: DiscoveryService,\n pluginId: string,\n ) {\n this.#auth = auth;\n this.#discovery = discovery;\n this.#pluginId = pluginId;\n }\n\n async #extractCredentialsFromRequest(req: Request) {\n const token = getTokenFromRequest(req);\n if (!token) {\n return await this.#auth.getNoneCredentials();\n }\n\n return await this.#auth.authenticate(token);\n }\n\n async #extractLimitedCredentialsFromRequest(req: Request) {\n const token = getTokenFromRequest(req);\n if (token) {\n return await this.#auth.authenticate(token, {\n allowLimitedAccess: true,\n });\n }\n\n const cookie = getCookieFromRequest(req);\n if (cookie) {\n return await this.#auth.authenticate(cookie, {\n allowLimitedAccess: true,\n });\n }\n\n return await this.#auth.getNoneCredentials();\n }\n\n async #getCredentials(req: RequestWithCredentials) {\n return (req[credentialsSymbol] ??=\n this.#extractCredentialsFromRequest(req));\n }\n\n async #getLimitedCredentials(req: RequestWithCredentials) {\n return (req[limitedCredentialsSymbol] ??=\n this.#extractLimitedCredentialsFromRequest(req));\n }\n\n async credentials<TAllowed extends keyof BackstagePrincipalTypes = 'unknown'>(\n req: Request,\n options?: {\n allow?: Array<TAllowed>;\n allowLimitedAccess?: boolean;\n },\n ): Promise<BackstageCredentials<BackstagePrincipalTypes[TAllowed]>> {\n // Limited and full credentials are treated as two separate cases, this lets\n // us avoid internal dependencies between the AuthService and\n // HttpAuthService implementations\n const credentials = options?.allowLimitedAccess\n ? await this.#getLimitedCredentials(req)\n : await this.#getCredentials(req);\n\n const allowed = options?.allow;\n if (!allowed) {\n return credentials as any;\n }\n\n if (this.#auth.isPrincipal(credentials, 'none')) {\n if (allowed.includes('none' as TAllowed)) {\n return credentials as any;\n }\n\n throw new AuthenticationError('Missing credentials');\n } else if (this.#auth.isPrincipal(credentials, 'user')) {\n if (allowed.includes('user' as TAllowed)) {\n return credentials as any;\n }\n\n throw new NotAllowedError(\n `This endpoint does not allow 'user' credentials`,\n );\n } else if (this.#auth.isPrincipal(credentials, 'service')) {\n if (allowed.includes('service' as TAllowed)) {\n return credentials as any;\n }\n\n throw new NotAllowedError(\n `This endpoint does not allow 'service' credentials`,\n );\n }\n\n throw new NotAllowedError(\n 'Unknown principal type, this should never happen',\n );\n }\n\n async issueUserCookie(\n res: Response,\n options?: { credentials?: BackstageCredentials },\n ): Promise<{ expiresAt: Date }> {\n if (res.headersSent) {\n throw new Error('Failed to issue user cookie, headers were already sent');\n }\n\n let credentials: BackstageCredentials<BackstageUserPrincipal>;\n if (options?.credentials) {\n if (this.#auth.isPrincipal(options.credentials, 'none')) {\n res.clearCookie(\n BACKSTAGE_AUTH_COOKIE,\n await this.#getCookieOptions(res.req),\n );\n return { expiresAt: new Date() };\n }\n if (!this.#auth.isPrincipal(options.credentials, 'user')) {\n throw new AuthenticationError(\n 'Refused to issue cookie for non-user principal',\n );\n }\n credentials = options.credentials;\n } else {\n credentials = await this.credentials(res.req, { allow: ['user'] });\n }\n\n const existingExpiresAt = await this.#existingCookieExpiration(res.req);\n if (existingExpiresAt && !willExpireSoon(existingExpiresAt)) {\n return { expiresAt: existingExpiresAt };\n }\n\n const { token, expiresAt } = await this.#auth.getLimitedUserToken(\n credentials,\n );\n if (!token) {\n throw new Error('User credentials is unexpectedly missing token');\n }\n\n res.cookie(BACKSTAGE_AUTH_COOKIE, token, {\n ...(await this.#getCookieOptions(res.req)),\n expires: expiresAt,\n });\n\n return { expiresAt };\n }\n\n async #getCookieOptions(_req: Request): Promise<{\n domain: string;\n httpOnly: true;\n secure: boolean;\n priority: 'high';\n sameSite: 'none' | 'lax';\n }> {\n // TODO: eventually we should read from `${req.protocol}://${req.hostname}`\n // once https://github.com/backstage/backstage/issues/24169 has landed\n const externalBaseUrlStr = await this.#discovery.getExternalBaseUrl(\n this.#pluginId,\n );\n const externalBaseUrl = new URL(externalBaseUrlStr);\n\n const secure =\n externalBaseUrl.protocol === 'https:' ||\n externalBaseUrl.hostname === 'localhost';\n\n return {\n domain: externalBaseUrl.hostname,\n httpOnly: true,\n secure,\n priority: 'high',\n sameSite: secure ? 'none' : 'lax',\n };\n }\n\n async #existingCookieExpiration(req: Request): Promise<Date | undefined> {\n const existingCookie = getCookieFromRequest(req);\n if (!existingCookie) {\n return undefined;\n }\n\n try {\n const existingCredentials = await this.#auth.authenticate(\n existingCookie,\n {\n allowLimitedAccess: true,\n },\n );\n if (!this.#auth.isPrincipal(existingCredentials, 'user')) {\n return undefined;\n }\n\n return existingCredentials.expiresAt;\n } catch (error) {\n if (error.name === 'AuthenticationError') {\n return undefined;\n }\n throw error;\n }\n }\n}\n\n/**\n * Authentication of HTTP requests.\n *\n * See {@link @backstage/code-plugin-api#HttpAuthService}\n * and {@link https://backstage.io/docs/backend-system/core-services/http-auth | the service docs}\n * for more information.\n *\n * @public\n */\nexport const httpAuthServiceFactory = createServiceFactory({\n service: coreServices.httpAuth,\n deps: {\n auth: coreServices.auth,\n discovery: coreServices.discovery,\n plugin: coreServices.pluginMetadata,\n },\n async factory({ auth, discovery, plugin }) {\n return new DefaultHttpAuthService(auth, discovery, plugin.getId());\n },\n});\n"],"names":["parseCookie","AuthenticationError","NotAllowedError","createServiceFactory","coreServices"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createAuthIntegrationRouter.cjs.js","sources":["../../../src/entrypoints/httpRouter/createAuthIntegrationRouter.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { AuthService } from '@backstage/backend-plugin-api';\nimport express from 'express';\nimport Router from 'express-promise-router';\n\nexport function createAuthIntegrationRouter(options: {\n auth: AuthService;\n}): express.Router {\n const router = Router();\n\n router.get('/.backstage/auth/v1/jwks.json', async (_req, res) => {\n const { keys } = await options.auth.listPublicServiceKeys();\n\n res.json({ keys });\n });\n\n return router;\n}\n"],"names":["Router"],"mappings":";;;;;;;;AAoBO,SAAS,4BAA4B,OAEzB,EAAA;AACjB,EAAA,MAAM,SAASA,uBAAO,EAAA
|
|
1
|
+
{"version":3,"file":"createAuthIntegrationRouter.cjs.js","sources":["../../../src/entrypoints/httpRouter/createAuthIntegrationRouter.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { AuthService } from '@backstage/backend-plugin-api';\nimport express from 'express';\nimport Router from 'express-promise-router';\n\nexport function createAuthIntegrationRouter(options: {\n auth: AuthService;\n}): express.Router {\n const router = Router();\n\n router.get('/.backstage/auth/v1/jwks.json', async (_req, res) => {\n const { keys } = await options.auth.listPublicServiceKeys();\n\n res.json({ keys });\n });\n\n return router;\n}\n"],"names":["Router"],"mappings":";;;;;;;;AAoBO,SAAS,4BAA4B,OAEzB,EAAA;AACjB,EAAA,MAAM,SAASA,uBAAO,EAAA;AAEtB,EAAA,MAAA,CAAO,GAAI,CAAA,+BAAA,EAAiC,OAAO,IAAA,EAAM,GAAQ,KAAA;AAC/D,IAAA,MAAM,EAAE,IAAK,EAAA,GAAI,MAAM,OAAA,CAAQ,KAAK,qBAAsB,EAAA;AAE1D,IAAI,GAAA,CAAA,IAAA,CAAK,EAAE,IAAA,EAAM,CAAA;AAAA,GAClB,CAAA;AAED,EAAO,OAAA,MAAA;AACT;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createCookieAuthRefreshMiddleware.cjs.js","sources":["../../../src/entrypoints/httpRouter/createCookieAuthRefreshMiddleware.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { AuthService, HttpAuthService } from '@backstage/backend-plugin-api';\nimport Router from 'express-promise-router';\n\nconst WELL_KNOWN_COOKIE_PATH_V1 = '/.backstage/auth/v1/cookie';\n\n/**\n * @public\n * Creates a middleware that can be used to refresh the cookie for the user.\n */\nexport function createCookieAuthRefreshMiddleware(options: {\n auth: AuthService;\n httpAuth: HttpAuthService;\n}) {\n const { auth, httpAuth } = options;\n const router = Router();\n\n // Endpoint that sets the cookie for the user\n router.get(WELL_KNOWN_COOKIE_PATH_V1, async (_, res) => {\n const { expiresAt } = await httpAuth.issueUserCookie(res);\n res.json({ expiresAt: expiresAt.toISOString() });\n });\n\n // Endpoint that removes the cookie for the user\n router.delete(WELL_KNOWN_COOKIE_PATH_V1, async (_, res) => {\n const credentials = await auth.getNoneCredentials();\n await httpAuth.issueUserCookie(res, { credentials });\n res.status(204).end();\n });\n\n return router;\n}\n"],"names":["Router"],"mappings":";;;;;;;;AAmBA,MAAM,yBAA4B,GAAA,4BAAA
|
|
1
|
+
{"version":3,"file":"createCookieAuthRefreshMiddleware.cjs.js","sources":["../../../src/entrypoints/httpRouter/createCookieAuthRefreshMiddleware.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { AuthService, HttpAuthService } from '@backstage/backend-plugin-api';\nimport Router from 'express-promise-router';\n\nconst WELL_KNOWN_COOKIE_PATH_V1 = '/.backstage/auth/v1/cookie';\n\n/**\n * @public\n * Creates a middleware that can be used to refresh the cookie for the user.\n */\nexport function createCookieAuthRefreshMiddleware(options: {\n auth: AuthService;\n httpAuth: HttpAuthService;\n}) {\n const { auth, httpAuth } = options;\n const router = Router();\n\n // Endpoint that sets the cookie for the user\n router.get(WELL_KNOWN_COOKIE_PATH_V1, async (_, res) => {\n const { expiresAt } = await httpAuth.issueUserCookie(res);\n res.json({ expiresAt: expiresAt.toISOString() });\n });\n\n // Endpoint that removes the cookie for the user\n router.delete(WELL_KNOWN_COOKIE_PATH_V1, async (_, res) => {\n const credentials = await auth.getNoneCredentials();\n await httpAuth.issueUserCookie(res, { credentials });\n res.status(204).end();\n });\n\n return router;\n}\n"],"names":["Router"],"mappings":";;;;;;;;AAmBA,MAAM,yBAA4B,GAAA,4BAAA;AAM3B,SAAS,kCAAkC,OAG/C,EAAA;AACD,EAAM,MAAA,EAAE,IAAM,EAAA,QAAA,EAAa,GAAA,OAAA;AAC3B,EAAA,MAAM,SAASA,uBAAO,EAAA;AAGtB,EAAA,MAAA,CAAO,GAAI,CAAA,yBAAA,EAA2B,OAAO,CAAA,EAAG,GAAQ,KAAA;AACtD,IAAA,MAAM,EAAE,SAAU,EAAA,GAAI,MAAM,QAAA,CAAS,gBAAgB,GAAG,CAAA;AACxD,IAAA,GAAA,CAAI,KAAK,EAAE,SAAA,EAAW,SAAU,CAAA,WAAA,IAAe,CAAA;AAAA,GAChD,CAAA;AAGD,EAAA,MAAA,CAAO,MAAO,CAAA,yBAAA,EAA2B,OAAO,CAAA,EAAG,GAAQ,KAAA;AACzD,IAAM,MAAA,WAAA,GAAc,MAAM,IAAA,CAAK,kBAAmB,EAAA;AAClD,IAAA,MAAM,QAAS,CAAA,eAAA,CAAgB,GAAK,EAAA,EAAE,aAAa,CAAA;AACnD,IAAI,GAAA,CAAA,MAAA,CAAO,GAAG,CAAA,CAAE,GAAI,EAAA;AAAA,GACrB,CAAA;AAED,EAAO,OAAA,MAAA;AACT;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createCredentialsBarrier.cjs.js","sources":["../../../src/entrypoints/httpRouter/createCredentialsBarrier.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n HttpAuthService,\n HttpRouterServiceAuthPolicy,\n RootConfigService,\n} from '@backstage/backend-plugin-api';\nimport { RequestHandler } from 'express';\nimport { pathToRegexp } from 'path-to-regexp';\n\nexport function createPathPolicyPredicate(policyPath: string) {\n if (policyPath === '/' || policyPath === '*') {\n return () => true;\n }\n\n const { regexp: pathRegex } = pathToRegexp(policyPath, {\n end: false,\n });\n\n return (path: string): boolean => {\n return pathRegex.test(path);\n };\n}\n\nexport function createCredentialsBarrier(options: {\n httpAuth: HttpAuthService;\n config: RootConfigService;\n}): {\n middleware: RequestHandler;\n addAuthPolicy: (policy: HttpRouterServiceAuthPolicy) => void;\n} {\n const { httpAuth, config } = options;\n\n const disableDefaultAuthPolicy = config.getOptionalBoolean(\n 'backend.auth.dangerouslyDisableDefaultAuthPolicy',\n );\n\n if (disableDefaultAuthPolicy) {\n return {\n middleware: (_req, _res, next) => next(),\n addAuthPolicy: () => {},\n };\n }\n\n const unauthenticatedPredicates = new Array<(path: string) => boolean>();\n const cookiePredicates = new Array<(path: string) => boolean>();\n\n const middleware: RequestHandler = (req, _, next) => {\n const allowsUnauthenticated = unauthenticatedPredicates.some(predicate =>\n predicate(req.path),\n );\n\n if (allowsUnauthenticated) {\n next();\n return;\n }\n\n const allowsCookie = cookiePredicates.some(predicate =>\n predicate(req.path),\n );\n\n httpAuth\n .credentials(req, {\n allow: ['user', 'service'],\n allowLimitedAccess: allowsCookie,\n })\n .then(\n () => next(),\n err => next(err),\n );\n };\n\n const addAuthPolicy = (policy: HttpRouterServiceAuthPolicy) => {\n if (policy.allow === 'unauthenticated') {\n unauthenticatedPredicates.push(createPathPolicyPredicate(policy.path));\n } else if (policy.allow === 'user-cookie') {\n cookiePredicates.push(createPathPolicyPredicate(policy.path));\n } else {\n throw new Error('Invalid auth policy');\n }\n };\n\n return { middleware, addAuthPolicy };\n}\n"],"names":["pathToRegexp"],"mappings":";;;;AAwBO,SAAS,0BAA0B,UAAoB,EAAA;AAC5D,EAAI,IAAA,UAAA,KAAe,GAAO,IAAA,UAAA,KAAe,GAAK,EAAA;AAC5C,IAAA,OAAO,MAAM,IAAA
|
|
1
|
+
{"version":3,"file":"createCredentialsBarrier.cjs.js","sources":["../../../src/entrypoints/httpRouter/createCredentialsBarrier.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n HttpAuthService,\n HttpRouterServiceAuthPolicy,\n RootConfigService,\n} from '@backstage/backend-plugin-api';\nimport { RequestHandler } from 'express';\nimport { pathToRegexp } from 'path-to-regexp';\n\nexport function createPathPolicyPredicate(policyPath: string) {\n if (policyPath === '/' || policyPath === '*') {\n return () => true;\n }\n\n const { regexp: pathRegex } = pathToRegexp(policyPath, {\n end: false,\n });\n\n return (path: string): boolean => {\n return pathRegex.test(path);\n };\n}\n\nexport function createCredentialsBarrier(options: {\n httpAuth: HttpAuthService;\n config: RootConfigService;\n}): {\n middleware: RequestHandler;\n addAuthPolicy: (policy: HttpRouterServiceAuthPolicy) => void;\n} {\n const { httpAuth, config } = options;\n\n const disableDefaultAuthPolicy = config.getOptionalBoolean(\n 'backend.auth.dangerouslyDisableDefaultAuthPolicy',\n );\n\n if (disableDefaultAuthPolicy) {\n return {\n middleware: (_req, _res, next) => next(),\n addAuthPolicy: () => {},\n };\n }\n\n const unauthenticatedPredicates = new Array<(path: string) => boolean>();\n const cookiePredicates = new Array<(path: string) => boolean>();\n\n const middleware: RequestHandler = (req, _, next) => {\n const allowsUnauthenticated = unauthenticatedPredicates.some(predicate =>\n predicate(req.path),\n );\n\n if (allowsUnauthenticated) {\n next();\n return;\n }\n\n const allowsCookie = cookiePredicates.some(predicate =>\n predicate(req.path),\n );\n\n httpAuth\n .credentials(req, {\n allow: ['user', 'service'],\n allowLimitedAccess: allowsCookie,\n })\n .then(\n () => next(),\n err => next(err),\n );\n };\n\n const addAuthPolicy = (policy: HttpRouterServiceAuthPolicy) => {\n if (policy.allow === 'unauthenticated') {\n unauthenticatedPredicates.push(createPathPolicyPredicate(policy.path));\n } else if (policy.allow === 'user-cookie') {\n cookiePredicates.push(createPathPolicyPredicate(policy.path));\n } else {\n throw new Error('Invalid auth policy');\n }\n };\n\n return { middleware, addAuthPolicy };\n}\n"],"names":["pathToRegexp"],"mappings":";;;;AAwBO,SAAS,0BAA0B,UAAoB,EAAA;AAC5D,EAAI,IAAA,UAAA,KAAe,GAAO,IAAA,UAAA,KAAe,GAAK,EAAA;AAC5C,IAAA,OAAO,MAAM,IAAA;AAAA;AAGf,EAAA,MAAM,EAAE,MAAA,EAAQ,SAAU,EAAA,GAAIA,0BAAa,UAAY,EAAA;AAAA,IACrD,GAAK,EAAA;AAAA,GACN,CAAA;AAED,EAAA,OAAO,CAAC,IAA0B,KAAA;AAChC,IAAO,OAAA,SAAA,CAAU,KAAK,IAAI,CAAA;AAAA,GAC5B;AACF;AAEO,SAAS,yBAAyB,OAMvC,EAAA;AACA,EAAM,MAAA,EAAE,QAAU,EAAA,MAAA,EAAW,GAAA,OAAA;AAE7B,EAAA,MAAM,2BAA2B,MAAO,CAAA,kBAAA;AAAA,IACtC;AAAA,GACF;AAEA,EAAA,IAAI,wBAA0B,EAAA;AAC5B,IAAO,OAAA;AAAA,MACL,UAAY,EAAA,CAAC,IAAM,EAAA,IAAA,EAAM,SAAS,IAAK,EAAA;AAAA,MACvC,eAAe,MAAM;AAAA;AAAC,KACxB;AAAA;AAGF,EAAM,MAAA,yBAAA,GAA4B,IAAI,KAAiC,EAAA;AACvE,EAAM,MAAA,gBAAA,GAAmB,IAAI,KAAiC,EAAA;AAE9D,EAAA,MAAM,UAA6B,GAAA,CAAC,GAAK,EAAA,CAAA,EAAG,IAAS,KAAA;AACnD,IAAA,MAAM,wBAAwB,yBAA0B,CAAA,IAAA;AAAA,MAAK,CAAA,SAAA,KAC3D,SAAU,CAAA,GAAA,CAAI,IAAI;AAAA,KACpB;AAEA,IAAA,IAAI,qBAAuB,EAAA;AACzB,MAAK,IAAA,EAAA;AACL,MAAA;AAAA;AAGF,IAAA,MAAM,eAAe,gBAAiB,CAAA,IAAA;AAAA,MAAK,CAAA,SAAA,KACzC,SAAU,CAAA,GAAA,CAAI,IAAI;AAAA,KACpB;AAEA,IAAA,QAAA,CACG,YAAY,GAAK,EAAA;AAAA,MAChB,KAAA,EAAO,CAAC,MAAA,EAAQ,SAAS,CAAA;AAAA,MACzB,kBAAoB,EAAA;AAAA,KACrB,CACA,CAAA,IAAA;AAAA,MACC,MAAM,IAAK,EAAA;AAAA,MACX,CAAA,GAAA,KAAO,KAAK,GAAG;AAAA,KACjB;AAAA,GACJ;AAEA,EAAM,MAAA,aAAA,GAAgB,CAAC,MAAwC,KAAA;AAC7D,IAAI,IAAA,MAAA,CAAO,UAAU,iBAAmB,EAAA;AACtC,MAAA,yBAAA,CAA0B,IAAK,CAAA,yBAAA,CAA0B,MAAO,CAAA,IAAI,CAAC,CAAA;AAAA,KACvE,MAAA,IAAW,MAAO,CAAA,KAAA,KAAU,aAAe,EAAA;AACzC,MAAA,gBAAA,CAAiB,IAAK,CAAA,yBAAA,CAA0B,MAAO,CAAA,IAAI,CAAC,CAAA;AAAA,KACvD,MAAA;AACL,MAAM,MAAA,IAAI,MAAM,qBAAqB,CAAA;AAAA;AACvC,GACF;AAEA,EAAO,OAAA,EAAE,YAAY,aAAc,EAAA;AACrC;;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createLifecycleMiddleware.cjs.js","sources":["../../../src/entrypoints/httpRouter/createLifecycleMiddleware.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { LifecycleService } from '@backstage/backend-plugin-api';\nimport { ServiceUnavailableError } from '@backstage/errors';\nimport { HumanDuration, durationToMilliseconds } from '@backstage/types';\nimport { RequestHandler } from 'express';\n\nexport const DEFAULT_TIMEOUT = { seconds: 5 };\n\n/**\n * Options for {@link createLifecycleMiddleware}.\n * @internal\n */\nexport interface LifecycleMiddlewareOptions {\n lifecycle: LifecycleService;\n /**\n * The maximum time that paused requests will wait for the service to start, before returning an error.\n *\n * Defaults to 5 seconds.\n */\n startupRequestPauseTimeout?: HumanDuration;\n}\n\n/**\n * Creates a middleware that pauses requests until the service has started.\n *\n * @remarks\n *\n * Requests that arrive before the service has started will be paused until startup is complete.\n * If the service does not start within the provided timeout, the request will be rejected with a\n * {@link @backstage/errors#ServiceUnavailableError}.\n *\n * If the service is shutting down, all requests will be rejected with a\n * {@link @backstage/errors#ServiceUnavailableError}.\n *\n * @internal\n */\nexport function createLifecycleMiddleware(\n options: LifecycleMiddlewareOptions,\n): RequestHandler {\n const { lifecycle, startupRequestPauseTimeout = DEFAULT_TIMEOUT } = options;\n\n let state: 'init' | 'up' | 'down' = 'init';\n const waiting = new Set<{\n next: (err?: Error) => void;\n timeout: NodeJS.Timeout;\n }>();\n\n lifecycle.addStartupHook(async () => {\n if (state === 'init') {\n state = 'up';\n for (const item of waiting) {\n clearTimeout(item.timeout);\n item.next();\n }\n waiting.clear();\n }\n });\n\n lifecycle.addShutdownHook(async () => {\n state = 'down';\n\n for (const item of waiting) {\n clearTimeout(item.timeout);\n item.next(new ServiceUnavailableError('Service is shutting down'));\n }\n waiting.clear();\n });\n\n const timeoutMs = durationToMilliseconds(startupRequestPauseTimeout);\n\n return (_req, _res, next) => {\n if (state === 'up') {\n next();\n return;\n } else if (state === 'down') {\n next(new ServiceUnavailableError('Service is shutting down'));\n return;\n }\n\n const item = {\n next,\n timeout: setTimeout(() => {\n if (waiting.delete(item)) {\n next(new ServiceUnavailableError('Service has not started up yet'));\n }\n }, timeoutMs),\n };\n\n waiting.add(item);\n };\n}\n"],"names":["ServiceUnavailableError","durationToMilliseconds"],"mappings":";;;;;AAqBa,MAAA,eAAA,GAAkB,EAAE,OAAA,EAAS,CAAE
|
|
1
|
+
{"version":3,"file":"createLifecycleMiddleware.cjs.js","sources":["../../../src/entrypoints/httpRouter/createLifecycleMiddleware.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { LifecycleService } from '@backstage/backend-plugin-api';\nimport { ServiceUnavailableError } from '@backstage/errors';\nimport { HumanDuration, durationToMilliseconds } from '@backstage/types';\nimport { RequestHandler } from 'express';\n\nexport const DEFAULT_TIMEOUT = { seconds: 5 };\n\n/**\n * Options for {@link createLifecycleMiddleware}.\n * @internal\n */\nexport interface LifecycleMiddlewareOptions {\n lifecycle: LifecycleService;\n /**\n * The maximum time that paused requests will wait for the service to start, before returning an error.\n *\n * Defaults to 5 seconds.\n */\n startupRequestPauseTimeout?: HumanDuration;\n}\n\n/**\n * Creates a middleware that pauses requests until the service has started.\n *\n * @remarks\n *\n * Requests that arrive before the service has started will be paused until startup is complete.\n * If the service does not start within the provided timeout, the request will be rejected with a\n * {@link @backstage/errors#ServiceUnavailableError}.\n *\n * If the service is shutting down, all requests will be rejected with a\n * {@link @backstage/errors#ServiceUnavailableError}.\n *\n * @internal\n */\nexport function createLifecycleMiddleware(\n options: LifecycleMiddlewareOptions,\n): RequestHandler {\n const { lifecycle, startupRequestPauseTimeout = DEFAULT_TIMEOUT } = options;\n\n let state: 'init' | 'up' | 'down' = 'init';\n const waiting = new Set<{\n next: (err?: Error) => void;\n timeout: NodeJS.Timeout;\n }>();\n\n lifecycle.addStartupHook(async () => {\n if (state === 'init') {\n state = 'up';\n for (const item of waiting) {\n clearTimeout(item.timeout);\n item.next();\n }\n waiting.clear();\n }\n });\n\n lifecycle.addShutdownHook(async () => {\n state = 'down';\n\n for (const item of waiting) {\n clearTimeout(item.timeout);\n item.next(new ServiceUnavailableError('Service is shutting down'));\n }\n waiting.clear();\n });\n\n const timeoutMs = durationToMilliseconds(startupRequestPauseTimeout);\n\n return (_req, _res, next) => {\n if (state === 'up') {\n next();\n return;\n } else if (state === 'down') {\n next(new ServiceUnavailableError('Service is shutting down'));\n return;\n }\n\n const item = {\n next,\n timeout: setTimeout(() => {\n if (waiting.delete(item)) {\n next(new ServiceUnavailableError('Service has not started up yet'));\n }\n }, timeoutMs),\n };\n\n waiting.add(item);\n };\n}\n"],"names":["ServiceUnavailableError","durationToMilliseconds"],"mappings":";;;;;AAqBa,MAAA,eAAA,GAAkB,EAAE,OAAA,EAAS,CAAE;AA8BrC,SAAS,0BACd,OACgB,EAAA;AAChB,EAAA,MAAM,EAAE,SAAA,EAAW,0BAA6B,GAAA,eAAA,EAAoB,GAAA,OAAA;AAEpE,EAAA,IAAI,KAAgC,GAAA,MAAA;AACpC,EAAM,MAAA,OAAA,uBAAc,GAGjB,EAAA;AAEH,EAAA,SAAA,CAAU,eAAe,YAAY;AACnC,IAAA,IAAI,UAAU,MAAQ,EAAA;AACpB,MAAQ,KAAA,GAAA,IAAA;AACR,MAAA,KAAA,MAAW,QAAQ,OAAS,EAAA;AAC1B,QAAA,YAAA,CAAa,KAAK,OAAO,CAAA;AACzB,QAAA,IAAA,CAAK,IAAK,EAAA;AAAA;AAEZ,MAAA,OAAA,CAAQ,KAAM,EAAA;AAAA;AAChB,GACD,CAAA;AAED,EAAA,SAAA,CAAU,gBAAgB,YAAY;AACpC,IAAQ,KAAA,GAAA,MAAA;AAER,IAAA,KAAA,MAAW,QAAQ,OAAS,EAAA;AAC1B,MAAA,YAAA,CAAa,KAAK,OAAO,CAAA;AACzB,MAAA,IAAA,CAAK,IAAK,CAAA,IAAIA,8BAAwB,CAAA,0BAA0B,CAAC,CAAA;AAAA;AAEnE,IAAA,OAAA,CAAQ,KAAM,EAAA;AAAA,GACf,CAAA;AAED,EAAM,MAAA,SAAA,GAAYC,6BAAuB,0BAA0B,CAAA;AAEnE,EAAO,OAAA,CAAC,IAAM,EAAA,IAAA,EAAM,IAAS,KAAA;AAC3B,IAAA,IAAI,UAAU,IAAM,EAAA;AAClB,MAAK,IAAA,EAAA;AACL,MAAA;AAAA,KACF,MAAA,IAAW,UAAU,MAAQ,EAAA;AAC3B,MAAK,IAAA,CAAA,IAAID,8BAAwB,CAAA,0BAA0B,CAAC,CAAA;AAC5D,MAAA;AAAA;AAGF,IAAA,MAAM,IAAO,GAAA;AAAA,MACX,IAAA;AAAA,MACA,OAAA,EAAS,WAAW,MAAM;AACxB,QAAI,IAAA,OAAA,CAAQ,MAAO,CAAA,IAAI,CAAG,EAAA;AACxB,UAAK,IAAA,CAAA,IAAIA,8BAAwB,CAAA,gCAAgC,CAAC,CAAA;AAAA;AACpE,SACC,SAAS;AAAA,KACd;AAEA,IAAA,OAAA,CAAQ,IAAI,IAAI,CAAA;AAAA,GAClB;AACF;;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"httpRouterServiceFactory.cjs.js","sources":["../../../src/entrypoints/httpRouter/httpRouterServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Handler } from 'express';\nimport PromiseRouter from 'express-promise-router';\nimport {\n coreServices,\n createServiceFactory,\n HttpRouterServiceAuthPolicy,\n} from '@backstage/backend-plugin-api';\nimport { createLifecycleMiddleware } from './createLifecycleMiddleware';\nimport { createCredentialsBarrier } from './createCredentialsBarrier';\nimport { createAuthIntegrationRouter } from './createAuthIntegrationRouter';\nimport { createCookieAuthRefreshMiddleware } from './createCookieAuthRefreshMiddleware';\n\n/**\n * HTTP route registration for plugins.\n *\n * See {@link @backstage/code-plugin-api#HttpRouterService}\n * and {@link https://backstage.io/docs/backend-system/core-services/http-router | the service docs}\n * for more information.\n *\n * @public\n */\nexport const httpRouterServiceFactory = createServiceFactory({\n service: coreServices.httpRouter,\n initialization: 'always',\n deps: {\n plugin: coreServices.pluginMetadata,\n config: coreServices.rootConfig,\n lifecycle: coreServices.lifecycle,\n rootHttpRouter: coreServices.rootHttpRouter,\n auth: coreServices.auth,\n httpAuth: coreServices.httpAuth,\n },\n async factory({ auth, httpAuth, config, plugin, rootHttpRouter, lifecycle }) {\n const router = PromiseRouter();\n\n rootHttpRouter.use(`/api/${plugin.getId()}`, router);\n\n const credentialsBarrier = createCredentialsBarrier({\n httpAuth,\n config,\n });\n\n router.use(createAuthIntegrationRouter({ auth }));\n router.use(createLifecycleMiddleware({ lifecycle }));\n router.use(credentialsBarrier.middleware);\n router.use(createCookieAuthRefreshMiddleware({ auth, httpAuth }));\n\n return {\n use(handler: Handler): void {\n router.use(handler);\n },\n addAuthPolicy(policy: HttpRouterServiceAuthPolicy): void {\n credentialsBarrier.addAuthPolicy(policy);\n },\n };\n },\n});\n"],"names":["createServiceFactory","coreServices","PromiseRouter","createCredentialsBarrier","createAuthIntegrationRouter","createLifecycleMiddleware","createCookieAuthRefreshMiddleware"],"mappings":";;;;;;;;;;;;;AAqCO,MAAM,2BAA2BA,qCAAqB,CAAA;AAAA,EAC3D,SAASC,6BAAa,CAAA,UAAA;AAAA,EACtB,cAAgB,EAAA,QAAA;AAAA,EAChB,IAAM,EAAA;AAAA,IACJ,QAAQA,6BAAa,CAAA,cAAA;AAAA,IACrB,QAAQA,6BAAa,CAAA,UAAA;AAAA,IACrB,WAAWA,6BAAa,CAAA,SAAA;AAAA,IACxB,gBAAgBA,6BAAa,CAAA,cAAA;AAAA,IAC7B,MAAMA,6BAAa,CAAA,IAAA;AAAA,IACnB,UAAUA,6BAAa,CAAA
|
|
1
|
+
{"version":3,"file":"httpRouterServiceFactory.cjs.js","sources":["../../../src/entrypoints/httpRouter/httpRouterServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Handler } from 'express';\nimport PromiseRouter from 'express-promise-router';\nimport {\n coreServices,\n createServiceFactory,\n HttpRouterServiceAuthPolicy,\n} from '@backstage/backend-plugin-api';\nimport { createLifecycleMiddleware } from './createLifecycleMiddleware';\nimport { createCredentialsBarrier } from './createCredentialsBarrier';\nimport { createAuthIntegrationRouter } from './createAuthIntegrationRouter';\nimport { createCookieAuthRefreshMiddleware } from './createCookieAuthRefreshMiddleware';\n\n/**\n * HTTP route registration for plugins.\n *\n * See {@link @backstage/code-plugin-api#HttpRouterService}\n * and {@link https://backstage.io/docs/backend-system/core-services/http-router | the service docs}\n * for more information.\n *\n * @public\n */\nexport const httpRouterServiceFactory = createServiceFactory({\n service: coreServices.httpRouter,\n initialization: 'always',\n deps: {\n plugin: coreServices.pluginMetadata,\n config: coreServices.rootConfig,\n lifecycle: coreServices.lifecycle,\n rootHttpRouter: coreServices.rootHttpRouter,\n auth: coreServices.auth,\n httpAuth: coreServices.httpAuth,\n },\n async factory({ auth, httpAuth, config, plugin, rootHttpRouter, lifecycle }) {\n const router = PromiseRouter();\n\n rootHttpRouter.use(`/api/${plugin.getId()}`, router);\n\n const credentialsBarrier = createCredentialsBarrier({\n httpAuth,\n config,\n });\n\n router.use(createAuthIntegrationRouter({ auth }));\n router.use(createLifecycleMiddleware({ lifecycle }));\n router.use(credentialsBarrier.middleware);\n router.use(createCookieAuthRefreshMiddleware({ auth, httpAuth }));\n\n return {\n use(handler: Handler): void {\n router.use(handler);\n },\n addAuthPolicy(policy: HttpRouterServiceAuthPolicy): void {\n credentialsBarrier.addAuthPolicy(policy);\n },\n };\n },\n});\n"],"names":["createServiceFactory","coreServices","PromiseRouter","createCredentialsBarrier","createAuthIntegrationRouter","createLifecycleMiddleware","createCookieAuthRefreshMiddleware"],"mappings":";;;;;;;;;;;;;AAqCO,MAAM,2BAA2BA,qCAAqB,CAAA;AAAA,EAC3D,SAASC,6BAAa,CAAA,UAAA;AAAA,EACtB,cAAgB,EAAA,QAAA;AAAA,EAChB,IAAM,EAAA;AAAA,IACJ,QAAQA,6BAAa,CAAA,cAAA;AAAA,IACrB,QAAQA,6BAAa,CAAA,UAAA;AAAA,IACrB,WAAWA,6BAAa,CAAA,SAAA;AAAA,IACxB,gBAAgBA,6BAAa,CAAA,cAAA;AAAA,IAC7B,MAAMA,6BAAa,CAAA,IAAA;AAAA,IACnB,UAAUA,6BAAa,CAAA;AAAA,GACzB;AAAA,EACA,MAAM,QAAQ,EAAE,IAAA,EAAM,UAAU,MAAQ,EAAA,MAAA,EAAQ,cAAgB,EAAA,SAAA,EAAa,EAAA;AAC3E,IAAA,MAAM,SAASC,uBAAc,EAAA;AAE7B,IAAA,cAAA,CAAe,IAAI,CAAQ,KAAA,EAAA,MAAA,CAAO,KAAM,EAAC,IAAI,MAAM,CAAA;AAEnD,IAAA,MAAM,qBAAqBC,iDAAyB,CAAA;AAAA,MAClD,QAAA;AAAA,MACA;AAAA,KACD,CAAA;AAED,IAAA,MAAA,CAAO,GAAI,CAAAC,uDAAA,CAA4B,EAAE,IAAA,EAAM,CAAC,CAAA;AAChD,IAAA,MAAA,CAAO,GAAI,CAAAC,mDAAA,CAA0B,EAAE,SAAA,EAAW,CAAC,CAAA;AACnD,IAAO,MAAA,CAAA,GAAA,CAAI,mBAAmB,UAAU,CAAA;AACxC,IAAA,MAAA,CAAO,IAAIC,mEAAkC,CAAA,EAAE,IAAM,EAAA,QAAA,EAAU,CAAC,CAAA;AAEhE,IAAO,OAAA;AAAA,MACL,IAAI,OAAwB,EAAA;AAC1B,QAAA,MAAA,CAAO,IAAI,OAAO,CAAA;AAAA,OACpB;AAAA,MACA,cAAc,MAA2C,EAAA;AACvD,QAAA,kBAAA,CAAmB,cAAc,MAAM,CAAA;AAAA;AACzC,KACF;AAAA;AAEJ,CAAC;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecycleServiceFactory.cjs.js","sources":["../../../src/entrypoints/lifecycle/lifecycleServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n LifecycleService,\n LifecycleServiceShutdownHook,\n LifecycleServiceShutdownOptions,\n LifecycleServiceStartupHook,\n LifecycleServiceStartupOptions,\n LoggerService,\n PluginMetadataService,\n coreServices,\n createServiceFactory,\n} from '@backstage/backend-plugin-api';\n\n/** @internal */\nexport class BackendPluginLifecycleImpl implements LifecycleService {\n constructor(\n private readonly logger: LoggerService,\n private readonly pluginMetadata: PluginMetadataService,\n ) {}\n\n #hasStarted = false;\n #hasShutdown = false;\n #startupTasks: Array<{\n hook: LifecycleServiceStartupHook;\n options?: LifecycleServiceStartupOptions;\n }> = [];\n #shutdownTasks: Array<{\n hook: LifecycleServiceShutdownHook;\n options?: LifecycleServiceShutdownOptions;\n }> = [];\n\n addStartupHook(\n hook: LifecycleServiceStartupHook,\n options?: LifecycleServiceStartupOptions,\n ): void {\n if (this.#hasStarted) {\n throw new Error('Attempted to add startup hook after startup');\n }\n this.#startupTasks.push({ hook, options });\n }\n\n async startup(): Promise<void> {\n if (this.#hasStarted) {\n return;\n }\n this.#hasStarted = true;\n\n this.logger.debug(\n `Running ${this.#startupTasks.length} plugin startup tasks...`,\n );\n await Promise.all(\n this.#startupTasks.map(async ({ hook, options }) => {\n const logger = options?.logger ?? this.logger;\n try {\n await hook();\n logger.debug(`Plugin startup hook succeeded`);\n } catch (error) {\n logger.error(`Plugin startup hook failed, ${error}`);\n }\n }),\n );\n }\n\n addShutdownHook(\n hook: LifecycleServiceShutdownHook,\n options?: LifecycleServiceShutdownOptions,\n ): void {\n if (this.#hasShutdown) {\n throw new Error('Attempted to add shutdown hook after shutdown');\n }\n const plugin = this.pluginMetadata.getId();\n const logger = options?.logger?.child({ plugin }) ?? this.logger;\n this.#shutdownTasks.push({\n hook,\n options: {\n ...options,\n logger,\n },\n });\n }\n\n async shutdown(): Promise<void> {\n if (this.#hasShutdown) {\n return;\n }\n this.#hasShutdown = true;\n\n this.logger.debug(\n `Running ${this.#shutdownTasks.length} plugin shutdown tasks...`,\n );\n\n await Promise.all(\n this.#shutdownTasks.map(async ({ hook, options }) => {\n const logger = options?.logger ?? this.logger;\n try {\n await hook();\n logger.debug(`Plugin shutdown hook succeeded`);\n } catch (error) {\n logger.error('Plugin shutdown hook failed', error);\n }\n }),\n );\n }\n}\n\n/**\n * Registration of plugin startup and shutdown lifecycle hooks.\n *\n * See {@link @backstage/code-plugin-api#LifecycleService}\n * and {@link https://backstage.io/docs/backend-system/core-services/lifecycle | the service docs}\n * for more information.\n *\n * @public\n */\nexport const lifecycleServiceFactory = createServiceFactory({\n service: coreServices.lifecycle,\n deps: {\n logger: coreServices.logger,\n pluginMetadata: coreServices.pluginMetadata,\n },\n async factory({ logger, pluginMetadata }) {\n return new BackendPluginLifecycleImpl(logger, pluginMetadata);\n },\n});\n"],"names":["createServiceFactory","coreServices"],"mappings":";;;;AA6BO,MAAM,0BAAuD,CAAA;AAAA,EAClE,WAAA,CACmB,QACA,cACjB,EAAA;AAFiB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA
|
|
1
|
+
{"version":3,"file":"lifecycleServiceFactory.cjs.js","sources":["../../../src/entrypoints/lifecycle/lifecycleServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n LifecycleService,\n LifecycleServiceShutdownHook,\n LifecycleServiceShutdownOptions,\n LifecycleServiceStartupHook,\n LifecycleServiceStartupOptions,\n LoggerService,\n PluginMetadataService,\n coreServices,\n createServiceFactory,\n} from '@backstage/backend-plugin-api';\n\n/** @internal */\nexport class BackendPluginLifecycleImpl implements LifecycleService {\n constructor(\n private readonly logger: LoggerService,\n private readonly pluginMetadata: PluginMetadataService,\n ) {}\n\n #hasStarted = false;\n #hasShutdown = false;\n #startupTasks: Array<{\n hook: LifecycleServiceStartupHook;\n options?: LifecycleServiceStartupOptions;\n }> = [];\n #shutdownTasks: Array<{\n hook: LifecycleServiceShutdownHook;\n options?: LifecycleServiceShutdownOptions;\n }> = [];\n\n addStartupHook(\n hook: LifecycleServiceStartupHook,\n options?: LifecycleServiceStartupOptions,\n ): void {\n if (this.#hasStarted) {\n throw new Error('Attempted to add startup hook after startup');\n }\n this.#startupTasks.push({ hook, options });\n }\n\n async startup(): Promise<void> {\n if (this.#hasStarted) {\n return;\n }\n this.#hasStarted = true;\n\n this.logger.debug(\n `Running ${this.#startupTasks.length} plugin startup tasks...`,\n );\n await Promise.all(\n this.#startupTasks.map(async ({ hook, options }) => {\n const logger = options?.logger ?? this.logger;\n try {\n await hook();\n logger.debug(`Plugin startup hook succeeded`);\n } catch (error) {\n logger.error(`Plugin startup hook failed, ${error}`);\n }\n }),\n );\n }\n\n addShutdownHook(\n hook: LifecycleServiceShutdownHook,\n options?: LifecycleServiceShutdownOptions,\n ): void {\n if (this.#hasShutdown) {\n throw new Error('Attempted to add shutdown hook after shutdown');\n }\n const plugin = this.pluginMetadata.getId();\n const logger = options?.logger?.child({ plugin }) ?? this.logger;\n this.#shutdownTasks.push({\n hook,\n options: {\n ...options,\n logger,\n },\n });\n }\n\n async shutdown(): Promise<void> {\n if (this.#hasShutdown) {\n return;\n }\n this.#hasShutdown = true;\n\n this.logger.debug(\n `Running ${this.#shutdownTasks.length} plugin shutdown tasks...`,\n );\n\n await Promise.all(\n this.#shutdownTasks.map(async ({ hook, options }) => {\n const logger = options?.logger ?? this.logger;\n try {\n await hook();\n logger.debug(`Plugin shutdown hook succeeded`);\n } catch (error) {\n logger.error('Plugin shutdown hook failed', error);\n }\n }),\n );\n }\n}\n\n/**\n * Registration of plugin startup and shutdown lifecycle hooks.\n *\n * See {@link @backstage/code-plugin-api#LifecycleService}\n * and {@link https://backstage.io/docs/backend-system/core-services/lifecycle | the service docs}\n * for more information.\n *\n * @public\n */\nexport const lifecycleServiceFactory = createServiceFactory({\n service: coreServices.lifecycle,\n deps: {\n logger: coreServices.logger,\n pluginMetadata: coreServices.pluginMetadata,\n },\n async factory({ logger, pluginMetadata }) {\n return new BackendPluginLifecycleImpl(logger, pluginMetadata);\n },\n});\n"],"names":["createServiceFactory","coreServices"],"mappings":";;;;AA6BO,MAAM,0BAAuD,CAAA;AAAA,EAClE,WAAA,CACmB,QACA,cACjB,EAAA;AAFiB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AACA,IAAA,IAAA,CAAA,cAAA,GAAA,cAAA;AAAA;AAChB,EAEH,WAAc,GAAA,KAAA;AAAA,EACd,YAAe,GAAA,KAAA;AAAA,EACf,gBAGK,EAAC;AAAA,EACN,iBAGK,EAAC;AAAA,EAEN,cAAA,CACE,MACA,OACM,EAAA;AACN,IAAA,IAAI,KAAK,WAAa,EAAA;AACpB,MAAM,MAAA,IAAI,MAAM,6CAA6C,CAAA;AAAA;AAE/D,IAAA,IAAA,CAAK,aAAc,CAAA,IAAA,CAAK,EAAE,IAAA,EAAM,SAAS,CAAA;AAAA;AAC3C,EAEA,MAAM,OAAyB,GAAA;AAC7B,IAAA,IAAI,KAAK,WAAa,EAAA;AACpB,MAAA;AAAA;AAEF,IAAA,IAAA,CAAK,WAAc,GAAA,IAAA;AAEnB,IAAA,IAAA,CAAK,MAAO,CAAA,KAAA;AAAA,MACV,CAAA,QAAA,EAAW,IAAK,CAAA,aAAA,CAAc,MAAM,CAAA,wBAAA;AAAA,KACtC;AACA,IAAA,MAAM,OAAQ,CAAA,GAAA;AAAA,MACZ,KAAK,aAAc,CAAA,GAAA,CAAI,OAAO,EAAE,IAAA,EAAM,SAAc,KAAA;AAClD,QAAM,MAAA,MAAA,GAAS,OAAS,EAAA,MAAA,IAAU,IAAK,CAAA,MAAA;AACvC,QAAI,IAAA;AACF,UAAA,MAAM,IAAK,EAAA;AACX,UAAA,MAAA,CAAO,MAAM,CAA+B,6BAAA,CAAA,CAAA;AAAA,iBACrC,KAAO,EAAA;AACd,UAAO,MAAA,CAAA,KAAA,CAAM,CAA+B,4BAAA,EAAA,KAAK,CAAE,CAAA,CAAA;AAAA;AACrD,OACD;AAAA,KACH;AAAA;AACF,EAEA,eAAA,CACE,MACA,OACM,EAAA;AACN,IAAA,IAAI,KAAK,YAAc,EAAA;AACrB,MAAM,MAAA,IAAI,MAAM,+CAA+C,CAAA;AAAA;AAEjE,IAAM,MAAA,MAAA,GAAS,IAAK,CAAA,cAAA,CAAe,KAAM,EAAA;AACzC,IAAM,MAAA,MAAA,GAAS,SAAS,MAAQ,EAAA,KAAA,CAAM,EAAE,MAAO,EAAC,KAAK,IAAK,CAAA,MAAA;AAC1D,IAAA,IAAA,CAAK,eAAe,IAAK,CAAA;AAAA,MACvB,IAAA;AAAA,MACA,OAAS,EAAA;AAAA,QACP,GAAG,OAAA;AAAA,QACH;AAAA;AACF,KACD,CAAA;AAAA;AACH,EAEA,MAAM,QAA0B,GAAA;AAC9B,IAAA,IAAI,KAAK,YAAc,EAAA;AACrB,MAAA;AAAA;AAEF,IAAA,IAAA,CAAK,YAAe,GAAA,IAAA;AAEpB,IAAA,IAAA,CAAK,MAAO,CAAA,KAAA;AAAA,MACV,CAAA,QAAA,EAAW,IAAK,CAAA,cAAA,CAAe,MAAM,CAAA,yBAAA;AAAA,KACvC;AAEA,IAAA,MAAM,OAAQ,CAAA,GAAA;AAAA,MACZ,KAAK,cAAe,CAAA,GAAA,CAAI,OAAO,EAAE,IAAA,EAAM,SAAc,KAAA;AACnD,QAAM,MAAA,MAAA,GAAS,OAAS,EAAA,MAAA,IAAU,IAAK,CAAA,MAAA;AACvC,QAAI,IAAA;AACF,UAAA,MAAM,IAAK,EAAA;AACX,UAAA,MAAA,CAAO,MAAM,CAAgC,8BAAA,CAAA,CAAA;AAAA,iBACtC,KAAO,EAAA;AACd,UAAO,MAAA,CAAA,KAAA,CAAM,+BAA+B,KAAK,CAAA;AAAA;AACnD,OACD;AAAA,KACH;AAAA;AAEJ;AAWO,MAAM,0BAA0BA,qCAAqB,CAAA;AAAA,EAC1D,SAASC,6BAAa,CAAA,SAAA;AAAA,EACtB,IAAM,EAAA;AAAA,IACJ,QAAQA,6BAAa,CAAA,MAAA;AAAA,IACrB,gBAAgBA,6BAAa,CAAA;AAAA,GAC/B;AAAA,EACA,MAAM,OAAA,CAAQ,EAAE,MAAA,EAAQ,gBAAkB,EAAA;AACxC,IAAO,OAAA,IAAI,0BAA2B,CAAA,MAAA,EAAQ,cAAc,CAAA;AAAA;AAEhE,CAAC;;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loggerServiceFactory.cjs.js","sources":["../../../src/entrypoints/logger/loggerServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createServiceFactory,\n coreServices,\n} from '@backstage/backend-plugin-api';\n\n/**\n * Plugin-level logging.\n *\n * See {@link @backstage/code-plugin-api#LoggerService}\n * and {@link https://backstage.io/docs/backend-system/core-services/logger | the service docs}\n * for more information.\n *\n * @public\n */\nexport const loggerServiceFactory = createServiceFactory({\n service: coreServices.logger,\n deps: {\n rootLogger: coreServices.rootLogger,\n plugin: coreServices.pluginMetadata,\n },\n factory({ rootLogger, plugin }) {\n return rootLogger.child({ plugin: plugin.getId() });\n },\n});\n"],"names":["createServiceFactory","coreServices"],"mappings":";;;;AA8BO,MAAM,uBAAuBA,qCAAqB,CAAA;AAAA,EACvD,SAASC,6BAAa,CAAA,MAAA;AAAA,EACtB,IAAM,EAAA;AAAA,IACJ,YAAYA,6BAAa,CAAA,UAAA;AAAA,IACzB,QAAQA,6BAAa,CAAA
|
|
1
|
+
{"version":3,"file":"loggerServiceFactory.cjs.js","sources":["../../../src/entrypoints/logger/loggerServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createServiceFactory,\n coreServices,\n} from '@backstage/backend-plugin-api';\n\n/**\n * Plugin-level logging.\n *\n * See {@link @backstage/code-plugin-api#LoggerService}\n * and {@link https://backstage.io/docs/backend-system/core-services/logger | the service docs}\n * for more information.\n *\n * @public\n */\nexport const loggerServiceFactory = createServiceFactory({\n service: coreServices.logger,\n deps: {\n rootLogger: coreServices.rootLogger,\n plugin: coreServices.pluginMetadata,\n },\n factory({ rootLogger, plugin }) {\n return rootLogger.child({ plugin: plugin.getId() });\n },\n});\n"],"names":["createServiceFactory","coreServices"],"mappings":";;;;AA8BO,MAAM,uBAAuBA,qCAAqB,CAAA;AAAA,EACvD,SAASC,6BAAa,CAAA,MAAA;AAAA,EACtB,IAAM,EAAA;AAAA,IACJ,YAAYA,6BAAa,CAAA,UAAA;AAAA,IACzB,QAAQA,6BAAa,CAAA;AAAA,GACvB;AAAA,EACA,OAAQ,CAAA,EAAE,UAAY,EAAA,MAAA,EAAU,EAAA;AAC9B,IAAA,OAAO,WAAW,KAAM,CAAA,EAAE,QAAQ,MAAO,CAAA,KAAA,IAAS,CAAA;AAAA;AAEtD,CAAC;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissionsServiceFactory.cjs.js","sources":["../../../src/entrypoints/permissions/permissionsServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createServiceFactory,\n} from '@backstage/backend-plugin-api';\nimport { ServerPermissionClient } from '@backstage/plugin-permission-node';\n\n/**\n * Permission system integration for authorization of user actions.\n *\n * See {@link @backstage/code-plugin-api#PermissionsService}\n * and {@link https://backstage.io/docs/backend-system/core-services/permissions | the service docs}\n * for more information.\n *\n * @public\n */\nexport const permissionsServiceFactory = createServiceFactory({\n service: coreServices.permissions,\n deps: {\n auth: coreServices.auth,\n config: coreServices.rootConfig,\n discovery: coreServices.discovery,\n },\n async factory({ auth, config, discovery }) {\n return ServerPermissionClient.fromConfig(config, {\n auth,\n discovery,\n });\n },\n});\n"],"names":["createServiceFactory","coreServices","ServerPermissionClient"],"mappings":";;;;;AA+BO,MAAM,4BAA4BA,qCAAqB,CAAA;AAAA,EAC5D,SAASC,6BAAa,CAAA,WAAA;AAAA,EACtB,IAAM,EAAA;AAAA,IACJ,MAAMA,6BAAa,CAAA,IAAA;AAAA,IACnB,QAAQA,6BAAa,CAAA,UAAA;AAAA,IACrB,WAAWA,6BAAa,CAAA
|
|
1
|
+
{"version":3,"file":"permissionsServiceFactory.cjs.js","sources":["../../../src/entrypoints/permissions/permissionsServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createServiceFactory,\n} from '@backstage/backend-plugin-api';\nimport { ServerPermissionClient } from '@backstage/plugin-permission-node';\n\n/**\n * Permission system integration for authorization of user actions.\n *\n * See {@link @backstage/code-plugin-api#PermissionsService}\n * and {@link https://backstage.io/docs/backend-system/core-services/permissions | the service docs}\n * for more information.\n *\n * @public\n */\nexport const permissionsServiceFactory = createServiceFactory({\n service: coreServices.permissions,\n deps: {\n auth: coreServices.auth,\n config: coreServices.rootConfig,\n discovery: coreServices.discovery,\n },\n async factory({ auth, config, discovery }) {\n return ServerPermissionClient.fromConfig(config, {\n auth,\n discovery,\n });\n },\n});\n"],"names":["createServiceFactory","coreServices","ServerPermissionClient"],"mappings":";;;;;AA+BO,MAAM,4BAA4BA,qCAAqB,CAAA;AAAA,EAC5D,SAASC,6BAAa,CAAA,WAAA;AAAA,EACtB,IAAM,EAAA;AAAA,IACJ,MAAMA,6BAAa,CAAA,IAAA;AAAA,IACnB,QAAQA,6BAAa,CAAA,UAAA;AAAA,IACrB,WAAWA,6BAAa,CAAA;AAAA,GAC1B;AAAA,EACA,MAAM,OAAQ,CAAA,EAAE,IAAM,EAAA,MAAA,EAAQ,WAAa,EAAA;AACzC,IAAO,OAAAC,2CAAA,CAAuB,WAAW,MAAQ,EAAA;AAAA,MAC/C,IAAA;AAAA,MACA;AAAA,KACD,CAAA;AAAA;AAEL,CAAC;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createConfigSecretEnumerator.cjs.js","sources":["../../../src/entrypoints/rootConfig/createConfigSecretEnumerator.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport type { Config } from '@backstage/config';\nimport { ConfigSchema, loadConfigSchema } from '@backstage/config-loader';\nimport { getPackages } from '@manypkg/get-packages';\n\n/** @public */\nexport async function createConfigSecretEnumerator(options: {\n logger: LoggerService;\n dir?: string;\n schema?: ConfigSchema;\n}): Promise<(config: Config) => Iterable<string>> {\n const { logger, dir = process.cwd() } = options;\n const { packages } = await getPackages(dir);\n const schema =\n options.schema ??\n (await loadConfigSchema({\n dependencies: packages.map(p => p.packageJson.name),\n }));\n\n return (config: Config) => {\n const [secretsData] = schema.process(\n [{ data: config.getOptional() ?? {}, context: 'schema-enumerator' }],\n {\n visibility: ['secret'],\n ignoreSchemaErrors: true,\n },\n );\n const secrets = new Set<string>();\n JSON.parse(\n JSON.stringify(secretsData.data),\n (_, v) => typeof v === 'string' && secrets.add(v),\n );\n logger.info(\n `Found ${secrets.size} new secrets in config that will be redacted`,\n );\n return secrets;\n };\n}\n"],"names":["getPackages","loadConfigSchema"],"mappings":";;;;;AAsBA,eAAsB,6BAA6B,OAID,EAAA;AAChD,EAAA,MAAM,EAAE,MAAQ,EAAA,GAAA,GAAM,OAAQ,CAAA,GAAA,IAAU,GAAA,OAAA
|
|
1
|
+
{"version":3,"file":"createConfigSecretEnumerator.cjs.js","sources":["../../../src/entrypoints/rootConfig/createConfigSecretEnumerator.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport type { Config } from '@backstage/config';\nimport { ConfigSchema, loadConfigSchema } from '@backstage/config-loader';\nimport { getPackages } from '@manypkg/get-packages';\n\n/** @public */\nexport async function createConfigSecretEnumerator(options: {\n logger: LoggerService;\n dir?: string;\n schema?: ConfigSchema;\n}): Promise<(config: Config) => Iterable<string>> {\n const { logger, dir = process.cwd() } = options;\n const { packages } = await getPackages(dir);\n const schema =\n options.schema ??\n (await loadConfigSchema({\n dependencies: packages.map(p => p.packageJson.name),\n }));\n\n return (config: Config) => {\n const [secretsData] = schema.process(\n [{ data: config.getOptional() ?? {}, context: 'schema-enumerator' }],\n {\n visibility: ['secret'],\n ignoreSchemaErrors: true,\n },\n );\n const secrets = new Set<string>();\n JSON.parse(\n JSON.stringify(secretsData.data),\n (_, v) => typeof v === 'string' && secrets.add(v),\n );\n logger.info(\n `Found ${secrets.size} new secrets in config that will be redacted`,\n );\n return secrets;\n };\n}\n"],"names":["getPackages","loadConfigSchema"],"mappings":";;;;;AAsBA,eAAsB,6BAA6B,OAID,EAAA;AAChD,EAAA,MAAM,EAAE,MAAQ,EAAA,GAAA,GAAM,OAAQ,CAAA,GAAA,IAAU,GAAA,OAAA;AACxC,EAAA,MAAM,EAAE,QAAA,EAAa,GAAA,MAAMA,wBAAY,GAAG,CAAA;AAC1C,EAAA,MAAM,MACJ,GAAA,OAAA,CAAQ,MACP,IAAA,MAAMC,6BAAiB,CAAA;AAAA,IACtB,cAAc,QAAS,CAAA,GAAA,CAAI,CAAK,CAAA,KAAA,CAAA,CAAE,YAAY,IAAI;AAAA,GACnD,CAAA;AAEH,EAAA,OAAO,CAAC,MAAmB,KAAA;AACzB,IAAM,MAAA,CAAC,WAAW,CAAA,GAAI,MAAO,CAAA,OAAA;AAAA,MAC3B,CAAC,EAAE,IAAA,EAAM,MAAO,CAAA,WAAA,MAAiB,EAAC,EAAG,OAAS,EAAA,mBAAA,EAAqB,CAAA;AAAA,MACnE;AAAA,QACE,UAAA,EAAY,CAAC,QAAQ,CAAA;AAAA,QACrB,kBAAoB,EAAA;AAAA;AACtB,KACF;AACA,IAAM,MAAA,OAAA,uBAAc,GAAY,EAAA;AAChC,IAAK,IAAA,CAAA,KAAA;AAAA,MACH,IAAA,CAAK,SAAU,CAAA,WAAA,CAAY,IAAI,CAAA;AAAA,MAC/B,CAAC,GAAG,CAAM,KAAA,OAAO,MAAM,QAAY,IAAA,OAAA,CAAQ,IAAI,CAAC;AAAA,KAClD;AACA,IAAO,MAAA,CAAA,IAAA;AAAA,MACL,CAAA,MAAA,EAAS,QAAQ,IAAI,CAAA,4CAAA;AAAA,KACvB;AACA,IAAO,OAAA,OAAA;AAAA,GACT;AACF;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rootConfigServiceFactory.cjs.js","sources":["../../../src/entrypoints/rootConfig/rootConfigServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createServiceFactory,\n} from '@backstage/backend-plugin-api';\nimport {\n ConfigSources,\n RemoteConfigSourceOptions,\n} from '@backstage/config-loader';\n\n/**\n * Access to static configuration.\n *\n * See {@link @backstage/code-plugin-api#RootConfigService}\n * and {@link https://backstage.io/docs/backend-system/core-services/root-config | the service docs}\n * for more information.\n *\n * @public\n */\nexport interface RootConfigFactoryOptions {\n /**\n * Process arguments to use instead of the default `process.argv()`.\n */\n argv?: string[];\n\n /**\n * Enables and sets options for remote configuration loading.\n */\n remote?: Pick<RemoteConfigSourceOptions, 'reloadInterval'>;\n watch?: boolean;\n}\n\nexport const rootConfigServiceFactoryWithOptions = (\n options?: RootConfigFactoryOptions,\n) =>\n createServiceFactory({\n service: coreServices.rootConfig,\n deps: {},\n async factory() {\n const source = ConfigSources.default({\n argv: options?.argv,\n remote: options?.remote,\n watch: options?.watch,\n });\n console.log(`Loading config from ${source}`);\n return await ConfigSources.toConfig(source);\n },\n });\n\n/**\n * @public\n */\nexport const rootConfigServiceFactory = Object.assign(\n rootConfigServiceFactoryWithOptions,\n rootConfigServiceFactoryWithOptions(),\n);\n"],"names":["createServiceFactory","coreServices","ConfigSources"],"mappings":";;;;;AA+Ca,MAAA,mCAAA,GAAsC,CACjD,OAAA,KAEAA,qCAAqB,CAAA;AAAA,EACnB,SAASC,6BAAa,CAAA,UAAA;AAAA,EACtB,MAAM,EAAC;AAAA,EACP,MAAM,OAAU,GAAA;AACd,IAAM,MAAA,MAAA,GAASC,2BAAc,OAAQ,CAAA;AAAA,MACnC,MAAM,OAAS,EAAA,IAAA;AAAA,MACf,QAAQ,OAAS,EAAA,MAAA;AAAA,MACjB,OAAO,OAAS,EAAA
|
|
1
|
+
{"version":3,"file":"rootConfigServiceFactory.cjs.js","sources":["../../../src/entrypoints/rootConfig/rootConfigServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createServiceFactory,\n} from '@backstage/backend-plugin-api';\nimport {\n ConfigSources,\n RemoteConfigSourceOptions,\n} from '@backstage/config-loader';\n\n/**\n * Access to static configuration.\n *\n * See {@link @backstage/code-plugin-api#RootConfigService}\n * and {@link https://backstage.io/docs/backend-system/core-services/root-config | the service docs}\n * for more information.\n *\n * @public\n */\nexport interface RootConfigFactoryOptions {\n /**\n * Process arguments to use instead of the default `process.argv()`.\n */\n argv?: string[];\n\n /**\n * Enables and sets options for remote configuration loading.\n */\n remote?: Pick<RemoteConfigSourceOptions, 'reloadInterval'>;\n watch?: boolean;\n}\n\nexport const rootConfigServiceFactoryWithOptions = (\n options?: RootConfigFactoryOptions,\n) =>\n createServiceFactory({\n service: coreServices.rootConfig,\n deps: {},\n async factory() {\n const source = ConfigSources.default({\n argv: options?.argv,\n remote: options?.remote,\n watch: options?.watch,\n });\n console.log(`Loading config from ${source}`);\n return await ConfigSources.toConfig(source);\n },\n });\n\n/**\n * @public\n */\nexport const rootConfigServiceFactory = Object.assign(\n rootConfigServiceFactoryWithOptions,\n rootConfigServiceFactoryWithOptions(),\n);\n"],"names":["createServiceFactory","coreServices","ConfigSources"],"mappings":";;;;;AA+Ca,MAAA,mCAAA,GAAsC,CACjD,OAAA,KAEAA,qCAAqB,CAAA;AAAA,EACnB,SAASC,6BAAa,CAAA,UAAA;AAAA,EACtB,MAAM,EAAC;AAAA,EACP,MAAM,OAAU,GAAA;AACd,IAAM,MAAA,MAAA,GAASC,2BAAc,OAAQ,CAAA;AAAA,MACnC,MAAM,OAAS,EAAA,IAAA;AAAA,MACf,QAAQ,OAAS,EAAA,MAAA;AAAA,MACjB,OAAO,OAAS,EAAA;AAAA,KACjB,CAAA;AACD,IAAQ,OAAA,CAAA,GAAA,CAAI,CAAuB,oBAAA,EAAA,MAAM,CAAE,CAAA,CAAA;AAC3C,IAAO,OAAA,MAAMA,0BAAc,CAAA,QAAA,CAAS,MAAM,CAAA;AAAA;AAE9C,CAAC;AAKI,MAAM,2BAA2B,MAAO,CAAA,MAAA;AAAA,EAC7C,mCAAA;AAAA,EACA,mCAAoC;AACtC;;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rootHealthServiceFactory.cjs.js","sources":["../../../src/entrypoints/rootHealth/rootHealthServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n RootHealthService,\n RootLifecycleService,\n coreServices,\n createServiceFactory,\n} from '@backstage/backend-plugin-api';\n\n/** @internal */\nexport class DefaultRootHealthService implements RootHealthService {\n #isRunning = false;\n\n constructor(readonly options: { lifecycle: RootLifecycleService }) {\n options.lifecycle.addStartupHook(() => {\n this.#isRunning = true;\n });\n options.lifecycle.addShutdownHook(() => {\n this.#isRunning = false;\n });\n }\n\n async getLiveness(): Promise<{ status: number; payload?: any }> {\n return { status: 200, payload: { status: 'ok' } };\n }\n\n async getReadiness(): Promise<{ status: number; payload?: any }> {\n if (!this.#isRunning) {\n return {\n status: 503,\n payload: { message: 'Backend has not started yet', status: 'error' },\n };\n }\n\n return { status: 200, payload: { status: 'ok' } };\n }\n}\n\n/**\n * @public\n */\nexport const rootHealthServiceFactory = createServiceFactory({\n service: coreServices.rootHealth,\n deps: {\n lifecycle: coreServices.rootLifecycle,\n },\n async factory({ lifecycle }) {\n return new DefaultRootHealthService({ lifecycle });\n },\n});\n"],"names":["createServiceFactory","coreServices"],"mappings":";;;;AAwBO,MAAM,wBAAsD,CAAA;AAAA,EAGjE,YAAqB,OAA8C,EAAA;AAA9C,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA
|
|
1
|
+
{"version":3,"file":"rootHealthServiceFactory.cjs.js","sources":["../../../src/entrypoints/rootHealth/rootHealthServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n RootHealthService,\n RootLifecycleService,\n coreServices,\n createServiceFactory,\n} from '@backstage/backend-plugin-api';\n\n/** @internal */\nexport class DefaultRootHealthService implements RootHealthService {\n #isRunning = false;\n\n constructor(readonly options: { lifecycle: RootLifecycleService }) {\n options.lifecycle.addStartupHook(() => {\n this.#isRunning = true;\n });\n options.lifecycle.addShutdownHook(() => {\n this.#isRunning = false;\n });\n }\n\n async getLiveness(): Promise<{ status: number; payload?: any }> {\n return { status: 200, payload: { status: 'ok' } };\n }\n\n async getReadiness(): Promise<{ status: number; payload?: any }> {\n if (!this.#isRunning) {\n return {\n status: 503,\n payload: { message: 'Backend has not started yet', status: 'error' },\n };\n }\n\n return { status: 200, payload: { status: 'ok' } };\n }\n}\n\n/**\n * @public\n */\nexport const rootHealthServiceFactory = createServiceFactory({\n service: coreServices.rootHealth,\n deps: {\n lifecycle: coreServices.rootLifecycle,\n },\n async factory({ lifecycle }) {\n return new DefaultRootHealthService({ lifecycle });\n },\n});\n"],"names":["createServiceFactory","coreServices"],"mappings":";;;;AAwBO,MAAM,wBAAsD,CAAA;AAAA,EAGjE,YAAqB,OAA8C,EAAA;AAA9C,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AACnB,IAAQ,OAAA,CAAA,SAAA,CAAU,eAAe,MAAM;AACrC,MAAA,IAAA,CAAK,UAAa,GAAA,IAAA;AAAA,KACnB,CAAA;AACD,IAAQ,OAAA,CAAA,SAAA,CAAU,gBAAgB,MAAM;AACtC,MAAA,IAAA,CAAK,UAAa,GAAA,KAAA;AAAA,KACnB,CAAA;AAAA;AACH,EATA,UAAa,GAAA,KAAA;AAAA,EAWb,MAAM,WAA0D,GAAA;AAC9D,IAAA,OAAO,EAAE,MAAQ,EAAA,GAAA,EAAK,SAAS,EAAE,MAAA,EAAQ,MAAO,EAAA;AAAA;AAClD,EAEA,MAAM,YAA2D,GAAA;AAC/D,IAAI,IAAA,CAAC,KAAK,UAAY,EAAA;AACpB,MAAO,OAAA;AAAA,QACL,MAAQ,EAAA,GAAA;AAAA,QACR,OAAS,EAAA,EAAE,OAAS,EAAA,6BAAA,EAA+B,QAAQ,OAAQ;AAAA,OACrE;AAAA;AAGF,IAAA,OAAO,EAAE,MAAQ,EAAA,GAAA,EAAK,SAAS,EAAE,MAAA,EAAQ,MAAO,EAAA;AAAA;AAEpD;AAKO,MAAM,2BAA2BA,qCAAqB,CAAA;AAAA,EAC3D,SAASC,6BAAa,CAAA,UAAA;AAAA,EACtB,IAAM,EAAA;AAAA,IACJ,WAAWA,6BAAa,CAAA;AAAA,GAC1B;AAAA,EACA,MAAM,OAAA,CAAQ,EAAE,SAAA,EAAa,EAAA;AAC3B,IAAA,OAAO,IAAI,wBAAA,CAAyB,EAAE,SAAA,EAAW,CAAA;AAAA;AAErD,CAAC;;;;;"}
|