@backstage/backend-defaults 0.5.1-next.0 → 0.5.1-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 +46 -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 +49 -0
- package/dist/CreateBackend.cjs.js.map +1 -0
- package/dist/PackageDiscoveryService.cjs.js +109 -0
- package/dist/PackageDiscoveryService.cjs.js.map +1 -0
- package/dist/auth.cjs.js +2 -996
- package/dist/auth.cjs.js.map +1 -1
- package/dist/cache.cjs.js +4 -204
- package/dist/cache.cjs.js.map +1 -1
- package/dist/database.cjs.js +4 -957
- package/dist/database.cjs.js.map +1 -1
- package/dist/database.d.ts +4 -1
- package/dist/discovery.cjs.js +4 -92
- package/dist/discovery.cjs.js.map +1 -1
- package/dist/discoveryFeatureLoader.cjs.js +19 -0
- package/dist/discoveryFeatureLoader.cjs.js.map +1 -0
- package/dist/entrypoints/auth/DefaultAuthService.cjs.js +130 -0
- package/dist/entrypoints/auth/DefaultAuthService.cjs.js.map +1 -0
- package/dist/entrypoints/auth/JwksClient.cjs.js +49 -0
- package/dist/entrypoints/auth/JwksClient.cjs.js.map +1 -0
- package/dist/entrypoints/auth/authServiceFactory.cjs.js +57 -0
- package/dist/entrypoints/auth/authServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/auth/external/ExternalTokenHandler.cjs.js +78 -0
- package/dist/entrypoints/auth/external/ExternalTokenHandler.cjs.js.map +1 -0
- package/dist/entrypoints/auth/external/helpers.cjs.js +92 -0
- package/dist/entrypoints/auth/external/helpers.cjs.js.map +1 -0
- package/dist/entrypoints/auth/external/jwks.cjs.js +63 -0
- package/dist/entrypoints/auth/external/jwks.cjs.js.map +1 -0
- package/dist/entrypoints/auth/external/legacy.cjs.js +73 -0
- package/dist/entrypoints/auth/external/legacy.cjs.js.map +1 -0
- package/dist/entrypoints/auth/external/static.cjs.js +33 -0
- package/dist/entrypoints/auth/external/static.cjs.js.map +1 -0
- package/dist/{cjs/helpers-D2f1CG0o.cjs.js → entrypoints/auth/helpers.cjs.js} +1 -1
- package/dist/entrypoints/auth/helpers.cjs.js.map +1 -0
- package/dist/entrypoints/auth/plugin/PluginTokenHandler.cjs.js +147 -0
- package/dist/entrypoints/auth/plugin/PluginTokenHandler.cjs.js.map +1 -0
- package/dist/entrypoints/auth/plugin/keys/DatabaseKeyStore.cjs.js +73 -0
- package/dist/entrypoints/auth/plugin/keys/DatabaseKeyStore.cjs.js.map +1 -0
- package/dist/entrypoints/auth/plugin/keys/DatabasePluginKeySource.cjs.js +75 -0
- package/dist/entrypoints/auth/plugin/keys/DatabasePluginKeySource.cjs.js.map +1 -0
- package/dist/entrypoints/auth/plugin/keys/StaticConfigPluginKeySource.cjs.js +91 -0
- package/dist/entrypoints/auth/plugin/keys/StaticConfigPluginKeySource.cjs.js.map +1 -0
- package/dist/entrypoints/auth/plugin/keys/createPluginKeySource.cjs.js +29 -0
- package/dist/entrypoints/auth/plugin/keys/createPluginKeySource.cjs.js.map +1 -0
- package/dist/entrypoints/auth/user/UserTokenHandler.cjs.js +110 -0
- package/dist/entrypoints/auth/user/UserTokenHandler.cjs.js.map +1 -0
- package/dist/entrypoints/cache/CacheClient.cjs.js +50 -0
- package/dist/entrypoints/cache/CacheClient.cjs.js.map +1 -0
- package/dist/entrypoints/cache/CacheManager.cjs.js +147 -0
- package/dist/entrypoints/cache/CacheManager.cjs.js.map +1 -0
- package/dist/entrypoints/cache/cacheServiceFactory.cjs.js +22 -0
- package/dist/entrypoints/cache/cacheServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/cache/types.cjs.js +10 -0
- package/dist/entrypoints/cache/types.cjs.js.map +1 -0
- package/dist/entrypoints/database/DatabaseManager.cjs.js +173 -0
- package/dist/entrypoints/database/DatabaseManager.cjs.js.map +1 -0
- package/dist/entrypoints/database/connectors/defaultNameOverride.cjs.js +14 -0
- package/dist/entrypoints/database/connectors/defaultNameOverride.cjs.js.map +1 -0
- package/dist/entrypoints/database/connectors/defaultSchemaOverride.cjs.js +12 -0
- package/dist/entrypoints/database/connectors/defaultSchemaOverride.cjs.js.map +1 -0
- package/dist/entrypoints/database/connectors/mergeDatabaseConfig.cjs.js +10 -0
- package/dist/entrypoints/database/connectors/mergeDatabaseConfig.cjs.js.map +1 -0
- package/dist/entrypoints/database/connectors/mysql.cjs.js +278 -0
- package/dist/entrypoints/database/connectors/mysql.cjs.js.map +1 -0
- package/dist/entrypoints/database/connectors/postgres.cjs.js +304 -0
- package/dist/entrypoints/database/connectors/postgres.cjs.js.map +1 -0
- package/dist/entrypoints/database/connectors/sqlite3.cjs.js +251 -0
- package/dist/entrypoints/database/connectors/sqlite3.cjs.js.map +1 -0
- package/dist/entrypoints/database/databaseServiceFactory.cjs.js +36 -0
- package/dist/entrypoints/database/databaseServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/discovery/HostDiscovery.cjs.js +86 -0
- package/dist/entrypoints/discovery/HostDiscovery.cjs.js.map +1 -0
- package/dist/entrypoints/discovery/discoveryServiceFactory.cjs.js +17 -0
- package/dist/entrypoints/discovery/discoveryServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/httpAuth/httpAuthServiceFactory.cjs.js +192 -0
- package/dist/entrypoints/httpAuth/httpAuthServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/httpRouter/createAuthIntegrationRouter.cjs.js +19 -0
- package/dist/entrypoints/httpRouter/createAuthIntegrationRouter.cjs.js.map +1 -0
- package/dist/entrypoints/httpRouter/createCookieAuthRefreshMiddleware.cjs.js +26 -0
- package/dist/entrypoints/httpRouter/createCookieAuthRefreshMiddleware.cjs.js.map +1 -0
- package/dist/entrypoints/httpRouter/createCredentialsBarrier.cjs.js +63 -0
- package/dist/entrypoints/httpRouter/createCredentialsBarrier.cjs.js.map +1 -0
- package/dist/entrypoints/httpRouter/createLifecycleMiddleware.cjs.js +52 -0
- package/dist/entrypoints/httpRouter/createLifecycleMiddleware.cjs.js.map +1 -0
- package/dist/entrypoints/httpRouter/httpRouterServiceFactory.cjs.js +48 -0
- package/dist/entrypoints/httpRouter/httpRouterServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/lifecycle/lifecycleServiceFactory.cjs.js +88 -0
- package/dist/entrypoints/lifecycle/lifecycleServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/logger/loggerServiceFactory.cjs.js +17 -0
- package/dist/entrypoints/logger/loggerServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/permissions/permissionsServiceFactory.cjs.js +22 -0
- package/dist/entrypoints/permissions/permissionsServiceFactory.cjs.js.map +1 -0
- package/dist/{cjs/createConfigSecretEnumerator-DShyoWWL.cjs.js → entrypoints/rootConfig/createConfigSecretEnumerator.cjs.js} +1 -1
- package/dist/entrypoints/rootConfig/createConfigSecretEnumerator.cjs.js.map +1 -0
- package/dist/entrypoints/rootConfig/rootConfigServiceFactory.cjs.js +26 -0
- package/dist/entrypoints/rootConfig/rootConfigServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/rootHealth/rootHealthServiceFactory.cjs.js +41 -0
- package/dist/entrypoints/rootHealth/rootHealthServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/rootHttpRouter/DefaultRootHttpRouter.cjs.js +77 -0
- package/dist/entrypoints/rootHttpRouter/DefaultRootHttpRouter.cjs.js.map +1 -0
- package/dist/entrypoints/rootHttpRouter/createHealthRouter.cjs.js +29 -0
- package/dist/entrypoints/rootHttpRouter/createHealthRouter.cjs.js.map +1 -0
- package/dist/entrypoints/rootHttpRouter/http/MiddlewareFactory.cjs.js +187 -0
- package/dist/entrypoints/rootHttpRouter/http/MiddlewareFactory.cjs.js.map +1 -0
- package/dist/entrypoints/rootHttpRouter/http/applyInternalErrorFilter.cjs.js +28 -0
- package/dist/entrypoints/rootHttpRouter/http/applyInternalErrorFilter.cjs.js.map +1 -0
- package/dist/{cjs/config-BDOwXIyo.cjs.js → entrypoints/rootHttpRouter/http/config.cjs.js} +1 -1
- package/dist/entrypoints/rootHttpRouter/http/config.cjs.js.map +1 -0
- package/dist/entrypoints/rootHttpRouter/http/createHttpServer.cjs.js +88 -0
- package/dist/entrypoints/rootHttpRouter/http/createHttpServer.cjs.js.map +1 -0
- package/dist/entrypoints/rootHttpRouter/http/getGeneratedCertificate.cjs.js +130 -0
- package/dist/entrypoints/rootHttpRouter/http/getGeneratedCertificate.cjs.js.map +1 -0
- package/dist/entrypoints/rootHttpRouter/http/readCorsOptions.cjs.js +51 -0
- package/dist/entrypoints/rootHttpRouter/http/readCorsOptions.cjs.js.map +1 -0
- package/dist/entrypoints/rootHttpRouter/http/readHelmetOptions.cjs.js +62 -0
- package/dist/entrypoints/rootHttpRouter/http/readHelmetOptions.cjs.js.map +1 -0
- package/dist/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.cjs.js +73 -0
- package/dist/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/rootLifecycle/rootLifecycleServiceFactory.cjs.js +76 -0
- package/dist/entrypoints/rootLifecycle/rootLifecycleServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/rootLogger/WinstonLogger.cjs.js +114 -0
- package/dist/entrypoints/rootLogger/WinstonLogger.cjs.js.map +1 -0
- package/dist/entrypoints/rootLogger/rootLoggerServiceFactory.cjs.js +30 -0
- package/dist/entrypoints/rootLogger/rootLoggerServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/scheduler/database/migrateBackendTasks.cjs.js +18 -0
- package/dist/entrypoints/scheduler/database/migrateBackendTasks.cjs.js.map +1 -0
- package/dist/entrypoints/scheduler/database/tables.cjs.js +8 -0
- package/dist/entrypoints/scheduler/database/tables.cjs.js.map +1 -0
- package/dist/entrypoints/scheduler/lib/DefaultSchedulerService.cjs.js +37 -0
- package/dist/entrypoints/scheduler/lib/DefaultSchedulerService.cjs.js.map +1 -0
- package/dist/entrypoints/scheduler/lib/LocalTaskWorker.cjs.js +105 -0
- package/dist/entrypoints/scheduler/lib/LocalTaskWorker.cjs.js.map +1 -0
- package/dist/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.cjs.js +138 -0
- package/dist/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.cjs.js.map +1 -0
- package/dist/entrypoints/scheduler/lib/PluginTaskSchedulerJanitor.cjs.js +59 -0
- package/dist/entrypoints/scheduler/lib/PluginTaskSchedulerJanitor.cjs.js.map +1 -0
- package/dist/entrypoints/scheduler/lib/TaskWorker.cjs.js +275 -0
- package/dist/entrypoints/scheduler/lib/TaskWorker.cjs.js.map +1 -0
- package/dist/entrypoints/scheduler/lib/types.cjs.js +60 -0
- package/dist/entrypoints/scheduler/lib/types.cjs.js.map +1 -0
- package/dist/entrypoints/scheduler/lib/util.cjs.js +66 -0
- package/dist/entrypoints/scheduler/lib/util.cjs.js.map +1 -0
- package/dist/entrypoints/scheduler/schedulerServiceFactory.cjs.js +19 -0
- package/dist/entrypoints/scheduler/schedulerServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/AwsCodeCommitUrlReader.cjs.js +274 -0
- package/dist/entrypoints/urlReader/lib/AwsCodeCommitUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/AwsS3UrlReader.cjs.js +261 -0
- package/dist/entrypoints/urlReader/lib/AwsS3UrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/AzureUrlReader.cjs.js +148 -0
- package/dist/entrypoints/urlReader/lib/AzureUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/BitbucketCloudUrlReader.cjs.js +174 -0
- package/dist/entrypoints/urlReader/lib/BitbucketCloudUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/BitbucketServerUrlReader.cjs.js +170 -0
- package/dist/entrypoints/urlReader/lib/BitbucketServerUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/BitbucketUrlReader.cjs.js +182 -0
- package/dist/entrypoints/urlReader/lib/BitbucketUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/FetchUrlReader.cjs.js +132 -0
- package/dist/entrypoints/urlReader/lib/FetchUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/GerritUrlReader.cjs.js +147 -0
- package/dist/entrypoints/urlReader/lib/GerritUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/GiteaUrlReader.cjs.js +122 -0
- package/dist/entrypoints/urlReader/lib/GiteaUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/GithubUrlReader.cjs.js +226 -0
- package/dist/entrypoints/urlReader/lib/GithubUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/GitlabUrlReader.cjs.js +277 -0
- package/dist/entrypoints/urlReader/lib/GitlabUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/GoogleGcsUrlReader.cjs.js +129 -0
- package/dist/entrypoints/urlReader/lib/GoogleGcsUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/HarnessUrlReader.cjs.js +120 -0
- package/dist/entrypoints/urlReader/lib/HarnessUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/ReadUrlResponseFactory.cjs.js +49 -0
- package/dist/entrypoints/urlReader/lib/ReadUrlResponseFactory.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/UrlReaderPredicateMux.cjs.js +46 -0
- package/dist/entrypoints/urlReader/lib/UrlReaderPredicateMux.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/UrlReaders.cjs.js +68 -0
- package/dist/entrypoints/urlReader/lib/UrlReaders.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/tree/ReadTreeResponseFactory.cjs.js +46 -0
- package/dist/entrypoints/urlReader/lib/tree/ReadTreeResponseFactory.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/tree/ReadableArrayResponse.cjs.js +78 -0
- package/dist/entrypoints/urlReader/lib/tree/ReadableArrayResponse.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/tree/TarArchiveResponse.cjs.js +147 -0
- package/dist/entrypoints/urlReader/lib/tree/TarArchiveResponse.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/tree/ZipArchiveResponse.cjs.js +161 -0
- package/dist/entrypoints/urlReader/lib/tree/ZipArchiveResponse.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/tree/util.cjs.js +28 -0
- package/dist/entrypoints/urlReader/lib/tree/util.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/util.cjs.js +11 -0
- package/dist/entrypoints/urlReader/lib/util.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/urlReaderServiceFactory.cjs.js +29 -0
- package/dist/entrypoints/urlReader/urlReaderServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/userInfo/DefaultUserInfoService.cjs.js +59 -0
- package/dist/entrypoints/userInfo/DefaultUserInfoService.cjs.js.map +1 -0
- package/dist/entrypoints/userInfo/userInfoServiceFactory.cjs.js +17 -0
- package/dist/entrypoints/userInfo/userInfoServiceFactory.cjs.js.map +1 -0
- package/dist/httpAuth.cjs.js +3 -187
- package/dist/httpAuth.cjs.js.map +1 -1
- package/dist/httpRouter.cjs.js +2 -166
- package/dist/httpRouter.cjs.js.map +1 -1
- package/dist/index.cjs.js +4 -160
- package/dist/index.cjs.js.map +1 -1
- package/dist/lib/escapeRegExp.cjs.js +8 -0
- package/dist/lib/escapeRegExp.cjs.js.map +1 -0
- package/dist/lifecycle.cjs.js +3 -58
- package/dist/lifecycle.cjs.js.map +1 -1
- package/dist/logger.cjs.js +3 -12
- package/dist/logger.cjs.js.map +1 -1
- package/dist/package.json.cjs.js +252 -0
- package/dist/package.json.cjs.js.map +1 -0
- package/dist/permissions.cjs.js +3 -17
- package/dist/permissions.cjs.js.map +1 -1
- package/dist/rootConfig.cjs.js +4 -22
- package/dist/rootConfig.cjs.js.map +1 -1
- package/dist/rootHealth.cjs.js +3 -35
- package/dist/rootHealth.cjs.js.map +1 -1
- package/dist/rootHttpRouter.cjs.js +15 -651
- package/dist/rootHttpRouter.cjs.js.map +1 -1
- package/dist/rootLifecycle.cjs.js +3 -70
- package/dist/rootLifecycle.cjs.js.map +1 -1
- package/dist/rootLogger.cjs.js +4 -137
- package/dist/rootLogger.cjs.js.map +1 -1
- package/dist/scheduler.cjs.js +4 -693
- package/dist/scheduler.cjs.js.map +1 -1
- package/dist/scheduler.d.ts +2 -1
- package/dist/urlReader.cjs.js +32 -2962
- package/dist/urlReader.cjs.js.map +1 -1
- package/dist/userInfo.cjs.js +2 -64
- package/dist/userInfo.cjs.js.map +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 +20 -20
- 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
- package/dist/cjs/config-BDOwXIyo.cjs.js.map +0 -1
- package/dist/cjs/createConfigSecretEnumerator-DShyoWWL.cjs.js.map +0 -1
- package/dist/cjs/helpers-D2f1CG0o.cjs.js.map +0 -1
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var config = require('@backstage/config');
|
|
4
|
+
var errors = require('@backstage/errors');
|
|
5
|
+
var knexFactory = require('knex');
|
|
6
|
+
var lodash = require('lodash');
|
|
7
|
+
var limiterFactory = require('p-limit');
|
|
8
|
+
var yn = require('yn');
|
|
9
|
+
var defaultNameOverride = require('./defaultNameOverride.cjs.js');
|
|
10
|
+
var mergeDatabaseConfig = require('./mergeDatabaseConfig.cjs.js');
|
|
11
|
+
|
|
12
|
+
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
13
|
+
|
|
14
|
+
var knexFactory__default = /*#__PURE__*/_interopDefaultCompat(knexFactory);
|
|
15
|
+
var limiterFactory__default = /*#__PURE__*/_interopDefaultCompat(limiterFactory);
|
|
16
|
+
var yn__default = /*#__PURE__*/_interopDefaultCompat(yn);
|
|
17
|
+
|
|
18
|
+
const ddlLimiter = limiterFactory__default.default(1);
|
|
19
|
+
function createMysqlDatabaseClient(dbConfig, overrides) {
|
|
20
|
+
const knexConfig = buildMysqlDatabaseConfig(dbConfig, overrides);
|
|
21
|
+
const database = knexFactory__default.default(knexConfig);
|
|
22
|
+
return database;
|
|
23
|
+
}
|
|
24
|
+
function buildMysqlDatabaseConfig(dbConfig, overrides) {
|
|
25
|
+
return mergeDatabaseConfig.mergeDatabaseConfig(
|
|
26
|
+
dbConfig.get(),
|
|
27
|
+
{
|
|
28
|
+
connection: getMysqlConnectionConfig(dbConfig, !!overrides),
|
|
29
|
+
useNullAsDefault: true
|
|
30
|
+
},
|
|
31
|
+
overrides
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
function getMysqlConnectionConfig(dbConfig, parseConnectionString) {
|
|
35
|
+
const connection = dbConfig.get("connection");
|
|
36
|
+
const isConnectionString = typeof connection === "string" || connection instanceof String;
|
|
37
|
+
const autoParse = typeof parseConnectionString !== "boolean";
|
|
38
|
+
const shouldParseConnectionString = autoParse ? isConnectionString : parseConnectionString && isConnectionString;
|
|
39
|
+
return shouldParseConnectionString ? parseMysqlConnectionString(connection) : connection;
|
|
40
|
+
}
|
|
41
|
+
function parseMysqlConnectionString(connectionString) {
|
|
42
|
+
try {
|
|
43
|
+
const {
|
|
44
|
+
protocol,
|
|
45
|
+
username,
|
|
46
|
+
password,
|
|
47
|
+
port,
|
|
48
|
+
hostname,
|
|
49
|
+
pathname,
|
|
50
|
+
searchParams
|
|
51
|
+
} = new URL(connectionString);
|
|
52
|
+
if (protocol !== "mysql:") {
|
|
53
|
+
throw new Error(`Unknown protocol ${protocol}`);
|
|
54
|
+
} else if (!username || !password) {
|
|
55
|
+
throw new Error(`Missing username/password`);
|
|
56
|
+
} else if (!pathname.match(/^\/[^/]+$/)) {
|
|
57
|
+
throw new Error(`Expected single path segment`);
|
|
58
|
+
}
|
|
59
|
+
const result = {
|
|
60
|
+
user: username,
|
|
61
|
+
password,
|
|
62
|
+
host: hostname,
|
|
63
|
+
port: Number(port || 3306),
|
|
64
|
+
database: decodeURIComponent(pathname.substring(1))
|
|
65
|
+
};
|
|
66
|
+
const ssl = searchParams.get("ssl");
|
|
67
|
+
if (ssl) {
|
|
68
|
+
result.ssl = ssl;
|
|
69
|
+
}
|
|
70
|
+
const debug = searchParams.get("debug");
|
|
71
|
+
if (debug) {
|
|
72
|
+
result.debug = yn__default.default(debug);
|
|
73
|
+
}
|
|
74
|
+
return result;
|
|
75
|
+
} catch (e) {
|
|
76
|
+
throw new errors.InputError(
|
|
77
|
+
`Error while parsing MySQL connection string, ${e}`,
|
|
78
|
+
e
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
async function ensureMysqlDatabaseExists(dbConfig, ...databases) {
|
|
83
|
+
const admin = createMysqlDatabaseClient(dbConfig, {
|
|
84
|
+
connection: {
|
|
85
|
+
database: null
|
|
86
|
+
},
|
|
87
|
+
pool: {
|
|
88
|
+
min: 0,
|
|
89
|
+
acquireTimeoutMillis: 1e4
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
try {
|
|
93
|
+
const ensureDatabase = async (database) => {
|
|
94
|
+
await admin.raw(`CREATE DATABASE IF NOT EXISTS ??`, [database]);
|
|
95
|
+
};
|
|
96
|
+
await Promise.all(
|
|
97
|
+
databases.map(async (database) => {
|
|
98
|
+
let lastErr = void 0;
|
|
99
|
+
for (let i = 0; i < 3; i++) {
|
|
100
|
+
try {
|
|
101
|
+
return await ddlLimiter(() => ensureDatabase(database));
|
|
102
|
+
} catch (err) {
|
|
103
|
+
lastErr = err;
|
|
104
|
+
}
|
|
105
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
106
|
+
}
|
|
107
|
+
throw lastErr;
|
|
108
|
+
})
|
|
109
|
+
);
|
|
110
|
+
} finally {
|
|
111
|
+
await admin.destroy();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
function pluginPath(pluginId) {
|
|
115
|
+
return `plugin.${pluginId}`;
|
|
116
|
+
}
|
|
117
|
+
function normalizeConnection(connection) {
|
|
118
|
+
if (typeof connection === "undefined" || connection === null) {
|
|
119
|
+
return {};
|
|
120
|
+
}
|
|
121
|
+
return typeof connection === "string" || connection instanceof String ? parseMysqlConnectionString(connection) : connection;
|
|
122
|
+
}
|
|
123
|
+
class MysqlConnector {
|
|
124
|
+
constructor(config, prefix) {
|
|
125
|
+
this.config = config;
|
|
126
|
+
this.prefix = prefix;
|
|
127
|
+
}
|
|
128
|
+
async getClient(pluginId, _deps) {
|
|
129
|
+
const pluginConfig = new config.ConfigReader(
|
|
130
|
+
this.getConfigForPlugin(pluginId)
|
|
131
|
+
);
|
|
132
|
+
const databaseName = this.getDatabaseName(pluginId);
|
|
133
|
+
if (databaseName && this.getEnsureExistsConfig(pluginId)) {
|
|
134
|
+
try {
|
|
135
|
+
await ensureMysqlDatabaseExists(pluginConfig, databaseName);
|
|
136
|
+
} catch (error) {
|
|
137
|
+
throw new Error(
|
|
138
|
+
`Failed to connect to the database to make sure that '${databaseName}' exists, ${error}`
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
const pluginDivisionMode = this.getPluginDivisionModeConfig();
|
|
143
|
+
if (pluginDivisionMode !== "database") {
|
|
144
|
+
throw new Error(
|
|
145
|
+
`The MySQL driver does not support plugin division mode '${pluginDivisionMode}'`
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
const databaseClientOverrides = mergeDatabaseConfig.mergeDatabaseConfig(
|
|
149
|
+
{},
|
|
150
|
+
this.getDatabaseOverrides(pluginId)
|
|
151
|
+
);
|
|
152
|
+
const client = createMysqlDatabaseClient(
|
|
153
|
+
pluginConfig,
|
|
154
|
+
databaseClientOverrides
|
|
155
|
+
);
|
|
156
|
+
return client;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Provides the canonical database name for a given plugin.
|
|
160
|
+
*
|
|
161
|
+
* This method provides the effective database name which is determined using
|
|
162
|
+
* global and plugin specific database config. If no explicit database name,
|
|
163
|
+
* this method will provide a generated name which is the pluginId prefixed
|
|
164
|
+
* with 'backstage_plugin_'.
|
|
165
|
+
*
|
|
166
|
+
* @param pluginId - Lookup the database name for given plugin
|
|
167
|
+
* @returns String representing the plugin's database name
|
|
168
|
+
*/
|
|
169
|
+
getDatabaseName(pluginId) {
|
|
170
|
+
const connection = this.getConnectionConfig(pluginId);
|
|
171
|
+
const databaseName = connection?.database;
|
|
172
|
+
return databaseName ?? `${this.prefix}${pluginId}`;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Provides the client type which should be used for a given plugin.
|
|
176
|
+
*
|
|
177
|
+
* The client type is determined by plugin specific config if present.
|
|
178
|
+
* Otherwise the base client is used as the fallback.
|
|
179
|
+
*
|
|
180
|
+
* @param pluginId - Plugin to get the client type for
|
|
181
|
+
* @returns Object with client type returned as `client` and boolean
|
|
182
|
+
* representing whether or not the client was overridden as
|
|
183
|
+
* `overridden`
|
|
184
|
+
*/
|
|
185
|
+
getClientType(pluginId) {
|
|
186
|
+
const pluginClient = this.config.getOptionalString(
|
|
187
|
+
`${pluginPath(pluginId)}.client`
|
|
188
|
+
);
|
|
189
|
+
const baseClient = this.config.getString("client");
|
|
190
|
+
const client = pluginClient ?? baseClient;
|
|
191
|
+
return {
|
|
192
|
+
client,
|
|
193
|
+
overridden: client !== baseClient
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
getRoleConfig(pluginId) {
|
|
197
|
+
return this.config.getOptionalString(`${pluginPath(pluginId)}.role`) ?? this.config.getOptionalString("role");
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Provides the knexConfig which should be used for a given plugin.
|
|
201
|
+
*
|
|
202
|
+
* @param pluginId - Plugin to get the knexConfig for
|
|
203
|
+
* @returns The merged knexConfig value or undefined if it isn't specified
|
|
204
|
+
*/
|
|
205
|
+
getAdditionalKnexConfig(pluginId) {
|
|
206
|
+
const pluginConfig = this.config.getOptionalConfig(`${pluginPath(pluginId)}.knexConfig`)?.get();
|
|
207
|
+
const baseConfig = this.config.getOptionalConfig("knexConfig")?.get();
|
|
208
|
+
return lodash.merge(baseConfig, pluginConfig);
|
|
209
|
+
}
|
|
210
|
+
getEnsureExistsConfig(pluginId) {
|
|
211
|
+
const baseConfig = this.config.getOptionalBoolean("ensureExists") ?? true;
|
|
212
|
+
return this.config.getOptionalBoolean(`${pluginPath(pluginId)}.ensureExists`) ?? baseConfig;
|
|
213
|
+
}
|
|
214
|
+
getPluginDivisionModeConfig() {
|
|
215
|
+
return this.config.getOptionalString("pluginDivisionMode") ?? "database";
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Provides a Knex connection plugin config by combining base and plugin
|
|
219
|
+
* config.
|
|
220
|
+
*
|
|
221
|
+
* This method provides a baseConfig for a plugin database connector. If the
|
|
222
|
+
* client type has not been overridden, the global connection config will be
|
|
223
|
+
* included with plugin specific config as the base. Values from the plugin
|
|
224
|
+
* connection take precedence over the base. Base database name is omitted
|
|
225
|
+
* unless `pluginDivisionMode` is set to `schema`.
|
|
226
|
+
*/
|
|
227
|
+
getConnectionConfig(pluginId) {
|
|
228
|
+
const { overridden } = this.getClientType(pluginId);
|
|
229
|
+
let baseConnection = normalizeConnection(this.config.get("connection"));
|
|
230
|
+
if (this.getPluginDivisionModeConfig() !== "schema") {
|
|
231
|
+
baseConnection = lodash.omit(baseConnection, "database");
|
|
232
|
+
}
|
|
233
|
+
const connection = normalizeConnection(
|
|
234
|
+
this.config.getOptional(`${pluginPath(pluginId)}.connection`)
|
|
235
|
+
);
|
|
236
|
+
return {
|
|
237
|
+
// include base connection if client type has not been overridden
|
|
238
|
+
...overridden ? {} : baseConnection,
|
|
239
|
+
...connection
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Provides a Knex database config for a given plugin.
|
|
244
|
+
*
|
|
245
|
+
* This method provides a Knex configuration object along with the plugin's
|
|
246
|
+
* client type.
|
|
247
|
+
*
|
|
248
|
+
* @param pluginId - The plugin that the database config should correspond with
|
|
249
|
+
*/
|
|
250
|
+
getConfigForPlugin(pluginId) {
|
|
251
|
+
const { client } = this.getClientType(pluginId);
|
|
252
|
+
const role = this.getRoleConfig(pluginId);
|
|
253
|
+
return {
|
|
254
|
+
...this.getAdditionalKnexConfig(pluginId),
|
|
255
|
+
client,
|
|
256
|
+
connection: this.getConnectionConfig(pluginId),
|
|
257
|
+
...role && { role }
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Provides a partial `Knex.Config`• database name override for a given plugin.
|
|
262
|
+
*
|
|
263
|
+
* @param pluginId - Target plugin to get database name override
|
|
264
|
+
* @returns Partial `Knex.Config` with database name override
|
|
265
|
+
*/
|
|
266
|
+
getDatabaseOverrides(pluginId) {
|
|
267
|
+
const databaseName = this.getDatabaseName(pluginId);
|
|
268
|
+
return databaseName ? defaultNameOverride.default(databaseName) : {};
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
exports.MysqlConnector = MysqlConnector;
|
|
273
|
+
exports.buildMysqlDatabaseConfig = buildMysqlDatabaseConfig;
|
|
274
|
+
exports.createMysqlDatabaseClient = createMysqlDatabaseClient;
|
|
275
|
+
exports.ensureMysqlDatabaseExists = ensureMysqlDatabaseExists;
|
|
276
|
+
exports.getMysqlConnectionConfig = getMysqlConnectionConfig;
|
|
277
|
+
exports.parseMysqlConnectionString = parseMysqlConnectionString;
|
|
278
|
+
//# sourceMappingURL=mysql.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mysql.cjs.js","sources":["../../../../src/entrypoints/database/connectors/mysql.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 { InputError } from '@backstage/errors';\nimport { JsonObject } from '@backstage/types';\nimport knexFactory, { Knex } from 'knex';\nimport { merge, omit } from 'lodash';\nimport limiterFactory from 'p-limit';\nimport yn from 'yn';\nimport { Connector } from '../types';\nimport defaultNameOverride from './defaultNameOverride';\nimport { mergeDatabaseConfig } from './mergeDatabaseConfig';\n\n// Limits the number of concurrent DDL operations to 1\nconst ddlLimiter = limiterFactory(1);\n\n/**\n * Creates a knex mysql database connection\n *\n * @param dbConfig - The database config\n * @param overrides - Additional options to merge with the config\n */\nexport function createMysqlDatabaseClient(\n dbConfig: Config,\n overrides?: Knex.Config,\n) {\n const knexConfig = buildMysqlDatabaseConfig(dbConfig, overrides);\n const database = knexFactory(knexConfig);\n return database;\n}\n\n/**\n * Builds a knex mysql database connection\n *\n * @param dbConfig - The database config\n * @param overrides - Additional options to merge with the config\n */\nexport function buildMysqlDatabaseConfig(\n dbConfig: Config,\n overrides?: Knex.Config,\n) {\n return mergeDatabaseConfig(\n dbConfig.get(),\n {\n connection: getMysqlConnectionConfig(dbConfig, !!overrides),\n useNullAsDefault: true,\n },\n overrides,\n );\n}\n\n/**\n * Gets the mysql connection config\n *\n * @param dbConfig - The database config\n * @param parseConnectionString - Flag to explicitly control connection string parsing\n */\nexport function getMysqlConnectionConfig(\n dbConfig: Config,\n parseConnectionString?: boolean,\n): Knex.MySqlConnectionConfig | 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 ? parseMysqlConnectionString(connection as string)\n : connection;\n}\n\n/**\n * Parses a mysql connection string.\n *\n * e.g. mysql://examplename:somepassword@examplehost:3306/dbname\n * @param connectionString - The mysql connection string\n */\nexport function parseMysqlConnectionString(\n connectionString: string,\n): Knex.MySqlConnectionConfig {\n try {\n const {\n protocol,\n username,\n password,\n port,\n hostname,\n pathname,\n searchParams,\n } = new URL(connectionString);\n\n if (protocol !== 'mysql:') {\n throw new Error(`Unknown protocol ${protocol}`);\n } else if (!username || !password) {\n throw new Error(`Missing username/password`);\n } else if (!pathname.match(/^\\/[^/]+$/)) {\n throw new Error(`Expected single path segment`);\n }\n\n const result: Knex.MySqlConnectionConfig = {\n user: username,\n password,\n host: hostname,\n port: Number(port || 3306),\n database: decodeURIComponent(pathname.substring(1)),\n };\n\n const ssl = searchParams.get('ssl');\n if (ssl) {\n result.ssl = ssl;\n }\n\n const debug = searchParams.get('debug');\n if (debug) {\n result.debug = yn(debug);\n }\n\n return result;\n } catch (e) {\n throw new InputError(\n `Error while parsing MySQL connection string, ${e}`,\n e,\n );\n }\n}\n\n/**\n * Creates the missing mysql database if it does not exist\n *\n * @param dbConfig - The database config\n * @param databases - The names of the databases to create\n */\nexport async function ensureMysqlDatabaseExists(\n dbConfig: Config,\n ...databases: Array<string>\n) {\n const admin = createMysqlDatabaseClient(dbConfig, {\n connection: {\n database: null as unknown as string,\n },\n pool: {\n min: 0,\n acquireTimeoutMillis: 10000,\n },\n });\n\n try {\n const ensureDatabase = async (database: string) => {\n await admin.raw(`CREATE DATABASE IF NOT EXISTS ??`, [database]);\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 * Drops the given mysql databases.\n *\n * @param dbConfig - The database config\n * @param databases - The names of the databases to create\n */\nexport async function dropMysqlDatabase(\n dbConfig: Config,\n ...databases: Array<string>\n) {\n const admin = createMysqlDatabaseClient(dbConfig, {\n connection: {\n database: null as unknown as string,\n },\n pool: {\n min: 0,\n acquireTimeoutMillis: 10000,\n },\n });\n\n try {\n const dropDatabase = async (database: string) => {\n await admin.raw(`DROP DATABASE ??`, [database]);\n };\n await Promise.all(\n databases.map(async database => {\n return await ddlLimiter(() => dropDatabase(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 ? parseMysqlConnectionString(connection as string)\n : connection;\n}\n\nexport class MysqlConnector 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 ensureMysqlDatabaseExists(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 const pluginDivisionMode = this.getPluginDivisionModeConfig();\n if (pluginDivisionMode !== 'database') {\n throw new Error(\n `The MySQL 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 = createMysqlDatabaseClient(\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\n * global and plugin specific database config. If no explicit database name,\n * this method will provide a generated name which is the pluginId prefixed\n * with 'backstage_plugin_'.\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 const databaseName = (connection as Knex.ConnectionConfig)?.database;\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 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 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","mergeDatabaseConfig","yn","InputError","ConfigReader","merge","omit","defaultNameOverride"],"mappings":"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"}
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var config = require('@backstage/config');
|
|
4
|
+
var errors = require('@backstage/errors');
|
|
5
|
+
var knexFactory = require('knex');
|
|
6
|
+
var lodash = require('lodash');
|
|
7
|
+
var limiterFactory = require('p-limit');
|
|
8
|
+
var defaultNameOverride = require('./defaultNameOverride.cjs.js');
|
|
9
|
+
var defaultSchemaOverride = require('./defaultSchemaOverride.cjs.js');
|
|
10
|
+
var mergeDatabaseConfig = require('./mergeDatabaseConfig.cjs.js');
|
|
11
|
+
var format = require('pg-format');
|
|
12
|
+
|
|
13
|
+
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
14
|
+
|
|
15
|
+
var knexFactory__default = /*#__PURE__*/_interopDefaultCompat(knexFactory);
|
|
16
|
+
var limiterFactory__default = /*#__PURE__*/_interopDefaultCompat(limiterFactory);
|
|
17
|
+
var format__default = /*#__PURE__*/_interopDefaultCompat(format);
|
|
18
|
+
|
|
19
|
+
const ddlLimiter = limiterFactory__default.default(1);
|
|
20
|
+
function createPgDatabaseClient(dbConfig, overrides) {
|
|
21
|
+
const knexConfig = buildPgDatabaseConfig(dbConfig, overrides);
|
|
22
|
+
const database = knexFactory__default.default(knexConfig);
|
|
23
|
+
const role = dbConfig.getOptionalString("role");
|
|
24
|
+
if (role) {
|
|
25
|
+
database.client.pool.on(
|
|
26
|
+
"createSuccess",
|
|
27
|
+
async (_event, pgClient) => {
|
|
28
|
+
const query = format__default.default("SET ROLE %I", role);
|
|
29
|
+
await pgClient.query(query);
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
return database;
|
|
34
|
+
}
|
|
35
|
+
function buildPgDatabaseConfig(dbConfig, overrides) {
|
|
36
|
+
return mergeDatabaseConfig.mergeDatabaseConfig(
|
|
37
|
+
dbConfig.get(),
|
|
38
|
+
{
|
|
39
|
+
connection: getPgConnectionConfig(dbConfig, !!overrides),
|
|
40
|
+
useNullAsDefault: true
|
|
41
|
+
},
|
|
42
|
+
overrides
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
function getPgConnectionConfig(dbConfig, parseConnectionString) {
|
|
46
|
+
const connection = dbConfig.get("connection");
|
|
47
|
+
const isConnectionString = typeof connection === "string" || connection instanceof String;
|
|
48
|
+
const autoParse = typeof parseConnectionString !== "boolean";
|
|
49
|
+
const shouldParseConnectionString = autoParse ? isConnectionString : parseConnectionString && isConnectionString;
|
|
50
|
+
return shouldParseConnectionString ? parsePgConnectionString(connection) : connection;
|
|
51
|
+
}
|
|
52
|
+
function parsePgConnectionString(connectionString) {
|
|
53
|
+
const parse = requirePgConnectionString();
|
|
54
|
+
return parse(connectionString);
|
|
55
|
+
}
|
|
56
|
+
function requirePgConnectionString() {
|
|
57
|
+
try {
|
|
58
|
+
return require("pg-connection-string").parse;
|
|
59
|
+
} catch (e) {
|
|
60
|
+
throw new errors.ForwardedError("Postgres: Install 'pg-connection-string'", e);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async function ensurePgDatabaseExists(dbConfig, ...databases) {
|
|
64
|
+
const admin = createPgDatabaseClient(dbConfig, {
|
|
65
|
+
connection: {
|
|
66
|
+
database: "postgres"
|
|
67
|
+
},
|
|
68
|
+
pool: {
|
|
69
|
+
min: 0,
|
|
70
|
+
acquireTimeoutMillis: 1e4
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
try {
|
|
74
|
+
const ensureDatabase = async (database) => {
|
|
75
|
+
const result = await admin.from("pg_database").where("datname", database).count();
|
|
76
|
+
if (parseInt(result[0].count, 10) > 0) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
await admin.raw(`CREATE DATABASE ??`, [database]);
|
|
80
|
+
};
|
|
81
|
+
await Promise.all(
|
|
82
|
+
databases.map(async (database) => {
|
|
83
|
+
let lastErr = void 0;
|
|
84
|
+
for (let i = 0; i < 3; i++) {
|
|
85
|
+
try {
|
|
86
|
+
return await ddlLimiter(() => ensureDatabase(database));
|
|
87
|
+
} catch (err) {
|
|
88
|
+
lastErr = err;
|
|
89
|
+
}
|
|
90
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
91
|
+
}
|
|
92
|
+
throw lastErr;
|
|
93
|
+
})
|
|
94
|
+
);
|
|
95
|
+
} finally {
|
|
96
|
+
await admin.destroy();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
async function ensurePgSchemaExists(dbConfig, ...schemas) {
|
|
100
|
+
const admin = createPgDatabaseClient(dbConfig);
|
|
101
|
+
const role = dbConfig.getOptionalString("role");
|
|
102
|
+
try {
|
|
103
|
+
const ensureSchema = async (database) => {
|
|
104
|
+
if (role) {
|
|
105
|
+
await admin.raw(`CREATE SCHEMA IF NOT EXISTS ?? AUTHORIZATION ??`, [
|
|
106
|
+
database,
|
|
107
|
+
role
|
|
108
|
+
]);
|
|
109
|
+
} else {
|
|
110
|
+
await admin.raw(`CREATE SCHEMA IF NOT EXISTS ??`, [database]);
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
await Promise.all(
|
|
114
|
+
schemas.map((database) => ddlLimiter(() => ensureSchema(database)))
|
|
115
|
+
);
|
|
116
|
+
} finally {
|
|
117
|
+
await admin.destroy();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
function pluginPath(pluginId) {
|
|
121
|
+
return `plugin.${pluginId}`;
|
|
122
|
+
}
|
|
123
|
+
function normalizeConnection(connection) {
|
|
124
|
+
if (typeof connection === "undefined" || connection === null) {
|
|
125
|
+
return {};
|
|
126
|
+
}
|
|
127
|
+
return typeof connection === "string" || connection instanceof String ? parsePgConnectionString(connection) : connection;
|
|
128
|
+
}
|
|
129
|
+
class PgConnector {
|
|
130
|
+
constructor(config, prefix) {
|
|
131
|
+
this.config = config;
|
|
132
|
+
this.prefix = prefix;
|
|
133
|
+
}
|
|
134
|
+
async getClient(pluginId, _deps) {
|
|
135
|
+
const pluginConfig = new config.ConfigReader(
|
|
136
|
+
this.getConfigForPlugin(pluginId)
|
|
137
|
+
);
|
|
138
|
+
const databaseName = this.getDatabaseName(pluginId);
|
|
139
|
+
if (databaseName && this.getEnsureExistsConfig(pluginId)) {
|
|
140
|
+
try {
|
|
141
|
+
await ensurePgDatabaseExists(pluginConfig, databaseName);
|
|
142
|
+
} catch (error) {
|
|
143
|
+
throw new Error(
|
|
144
|
+
`Failed to connect to the database to make sure that '${databaseName}' exists, ${error}`
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
let schemaOverrides;
|
|
149
|
+
if (this.getPluginDivisionModeConfig() === "schema") {
|
|
150
|
+
schemaOverrides = defaultSchemaOverride.default(pluginId);
|
|
151
|
+
if (this.getEnsureSchemaExistsConfig(pluginId) || this.getEnsureExistsConfig(pluginId)) {
|
|
152
|
+
try {
|
|
153
|
+
await ensurePgSchemaExists(pluginConfig, pluginId);
|
|
154
|
+
} catch (error) {
|
|
155
|
+
throw new Error(
|
|
156
|
+
`Failed to connect to the database to make sure that schema for plugin '${pluginId}' exists, ${error}`
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
const databaseClientOverrides = mergeDatabaseConfig.mergeDatabaseConfig(
|
|
162
|
+
{},
|
|
163
|
+
this.getDatabaseOverrides(pluginId),
|
|
164
|
+
schemaOverrides
|
|
165
|
+
);
|
|
166
|
+
const client = createPgDatabaseClient(
|
|
167
|
+
pluginConfig,
|
|
168
|
+
databaseClientOverrides
|
|
169
|
+
);
|
|
170
|
+
return client;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Provides the canonical database name for a given plugin.
|
|
174
|
+
*
|
|
175
|
+
* This method provides the effective database name which is determined using global
|
|
176
|
+
* and plugin specific database config. If no explicit database name is configured
|
|
177
|
+
* and `pluginDivisionMode` is not `schema`, this method will provide a generated name
|
|
178
|
+
* which is the pluginId prefixed with 'backstage_plugin_'. If `pluginDivisionMode` is
|
|
179
|
+
* `schema`, it will fallback to using the default database for the knex instance.
|
|
180
|
+
*
|
|
181
|
+
* @param pluginId - Lookup the database name for given plugin
|
|
182
|
+
* @returns String representing the plugin's database name
|
|
183
|
+
*/
|
|
184
|
+
getDatabaseName(pluginId) {
|
|
185
|
+
const connection = this.getConnectionConfig(pluginId);
|
|
186
|
+
const databaseName = connection?.database;
|
|
187
|
+
if (this.getPluginDivisionModeConfig() === "schema") {
|
|
188
|
+
return databaseName;
|
|
189
|
+
}
|
|
190
|
+
return databaseName ?? `${this.prefix}${pluginId}`;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Provides the client type which should be used for a given plugin.
|
|
194
|
+
*
|
|
195
|
+
* The client type is determined by plugin specific config if present.
|
|
196
|
+
* Otherwise the base client is used as the fallback.
|
|
197
|
+
*
|
|
198
|
+
* @param pluginId - Plugin to get the client type for
|
|
199
|
+
* @returns Object with client type returned as `client` and boolean
|
|
200
|
+
* representing whether or not the client was overridden as
|
|
201
|
+
* `overridden`
|
|
202
|
+
*/
|
|
203
|
+
getClientType(pluginId) {
|
|
204
|
+
const pluginClient = this.config.getOptionalString(
|
|
205
|
+
`${pluginPath(pluginId)}.client`
|
|
206
|
+
);
|
|
207
|
+
const baseClient = this.config.getString("client");
|
|
208
|
+
const client = pluginClient ?? baseClient;
|
|
209
|
+
return {
|
|
210
|
+
client,
|
|
211
|
+
overridden: client !== baseClient
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
getRoleConfig(pluginId) {
|
|
215
|
+
return this.config.getOptionalString(`${pluginPath(pluginId)}.role`) ?? this.config.getOptionalString("role");
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Provides the knexConfig which should be used for a given plugin.
|
|
219
|
+
*
|
|
220
|
+
* @param pluginId - Plugin to get the knexConfig for
|
|
221
|
+
* @returns The merged knexConfig value or undefined if it isn't specified
|
|
222
|
+
*/
|
|
223
|
+
getAdditionalKnexConfig(pluginId) {
|
|
224
|
+
const pluginConfig = this.config.getOptionalConfig(`${pluginPath(pluginId)}.knexConfig`)?.get();
|
|
225
|
+
const baseConfig = this.config.getOptionalConfig("knexConfig")?.get();
|
|
226
|
+
return lodash.merge(baseConfig, pluginConfig);
|
|
227
|
+
}
|
|
228
|
+
getEnsureExistsConfig(pluginId) {
|
|
229
|
+
const baseConfig = this.config.getOptionalBoolean("ensureExists") ?? true;
|
|
230
|
+
return this.config.getOptionalBoolean(`${pluginPath(pluginId)}.ensureExists`) ?? baseConfig;
|
|
231
|
+
}
|
|
232
|
+
getEnsureSchemaExistsConfig(pluginId) {
|
|
233
|
+
const baseConfig = this.config.getOptionalBoolean("ensureSchemaExists") ?? false;
|
|
234
|
+
return this.config.getOptionalBoolean(
|
|
235
|
+
`${pluginPath(pluginId)}.getEnsureSchemaExistsConfig`
|
|
236
|
+
) ?? baseConfig;
|
|
237
|
+
}
|
|
238
|
+
getPluginDivisionModeConfig() {
|
|
239
|
+
return this.config.getOptionalString("pluginDivisionMode") ?? "database";
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Provides a Knex connection plugin config by combining base and plugin
|
|
243
|
+
* config.
|
|
244
|
+
*
|
|
245
|
+
* This method provides a baseConfig for a plugin database connector. If the
|
|
246
|
+
* client type has not been overridden, the global connection config will be
|
|
247
|
+
* included with plugin specific config as the base. Values from the plugin
|
|
248
|
+
* connection take precedence over the base. Base database name is omitted
|
|
249
|
+
* unless `pluginDivisionMode` is set to `schema`.
|
|
250
|
+
*/
|
|
251
|
+
getConnectionConfig(pluginId) {
|
|
252
|
+
const { overridden } = this.getClientType(pluginId);
|
|
253
|
+
let baseConnection = normalizeConnection(this.config.get("connection"));
|
|
254
|
+
if (this.getPluginDivisionModeConfig() !== "schema") {
|
|
255
|
+
baseConnection = lodash.omit(baseConnection, "database");
|
|
256
|
+
}
|
|
257
|
+
const connection = normalizeConnection(
|
|
258
|
+
this.config.getOptional(`${pluginPath(pluginId)}.connection`)
|
|
259
|
+
);
|
|
260
|
+
baseConnection.application_name ||= `backstage_plugin_${pluginId}`;
|
|
261
|
+
return {
|
|
262
|
+
// include base connection if client type has not been overridden
|
|
263
|
+
...overridden ? {} : baseConnection,
|
|
264
|
+
...connection
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Provides a Knex database config for a given plugin.
|
|
269
|
+
*
|
|
270
|
+
* This method provides a Knex configuration object along with the plugin's
|
|
271
|
+
* client type.
|
|
272
|
+
*
|
|
273
|
+
* @param pluginId - The plugin that the database config should correspond with
|
|
274
|
+
*/
|
|
275
|
+
getConfigForPlugin(pluginId) {
|
|
276
|
+
const { client } = this.getClientType(pluginId);
|
|
277
|
+
const role = this.getRoleConfig(pluginId);
|
|
278
|
+
return {
|
|
279
|
+
...this.getAdditionalKnexConfig(pluginId),
|
|
280
|
+
client,
|
|
281
|
+
connection: this.getConnectionConfig(pluginId),
|
|
282
|
+
...role && { role }
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Provides a partial `Knex.Config`• database name override for a given plugin.
|
|
287
|
+
*
|
|
288
|
+
* @param pluginId - Target plugin to get database name override
|
|
289
|
+
* @returns Partial `Knex.Config` with database name override
|
|
290
|
+
*/
|
|
291
|
+
getDatabaseOverrides(pluginId) {
|
|
292
|
+
const databaseName = this.getDatabaseName(pluginId);
|
|
293
|
+
return databaseName ? defaultNameOverride.default(databaseName) : {};
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
exports.PgConnector = PgConnector;
|
|
298
|
+
exports.buildPgDatabaseConfig = buildPgDatabaseConfig;
|
|
299
|
+
exports.createPgDatabaseClient = createPgDatabaseClient;
|
|
300
|
+
exports.ensurePgDatabaseExists = ensurePgDatabaseExists;
|
|
301
|
+
exports.ensurePgSchemaExists = ensurePgSchemaExists;
|
|
302
|
+
exports.getPgConnectionConfig = getPgConnectionConfig;
|
|
303
|
+
exports.parsePgConnectionString = parsePgConnectionString;
|
|
304
|
+
//# sourceMappingURL=postgres.cjs.js.map
|