@backstage/backend-defaults 0.16.1-next.2 → 0.17.1-next.0
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 +54 -0
- package/config.d.ts +29 -0
- package/dist/CreateBackend.cjs.js.map +1 -1
- package/dist/entrypoints/database/connectors/postgres.cjs.js +83 -27
- package/dist/entrypoints/database/connectors/postgres.cjs.js.map +1 -1
- package/dist/entrypoints/scheduler/lib/types.cjs.js +0 -12
- package/dist/entrypoints/scheduler/lib/types.cjs.js.map +1 -1
- package/dist/entrypoints/scheduler/lib/util.cjs.js +19 -5
- package/dist/entrypoints/scheduler/lib/util.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/lib/util.cjs.js +0 -1
- package/dist/entrypoints/urlReader/lib/util.cjs.js.map +1 -1
- package/dist/index.cjs.js +1 -0
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/package.json.cjs.js +1 -1
- package/package.json +16 -16
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,59 @@
|
|
|
1
1
|
# @backstage/backend-defaults
|
|
2
2
|
|
|
3
|
+
## 0.17.1-next.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 3595c97: Exported `defaultServiceFactories` to allow use with `createSpecializedBackend` for advanced configuration like `extensionPointFactoryMiddleware`.
|
|
8
|
+
- 89d3248: Fixed scheduler `sleep` firing immediately for durations longer than ~24.8 days, caused by Node.js `setTimeout` overflowing its 32-bit millisecond limit.
|
|
9
|
+
- 744fa1f: Removed duplicated entries that appeared in both `dependencies` and `devDependencies`.
|
|
10
|
+
- Updated dependencies
|
|
11
|
+
- @backstage/errors@1.3.1-next.0
|
|
12
|
+
- @backstage/backend-app-api@1.7.0-next.0
|
|
13
|
+
- @backstage/integration@2.0.2-next.0
|
|
14
|
+
- @backstage/plugin-auth-node@0.7.1-next.0
|
|
15
|
+
- @backstage/backend-plugin-api@1.9.1-next.0
|
|
16
|
+
- @backstage/cli-node@0.3.2-next.0
|
|
17
|
+
- @backstage/config@1.3.8-next.0
|
|
18
|
+
- @backstage/config-loader@1.10.11-next.0
|
|
19
|
+
- @backstage/integration-aws-node@0.1.22-next.0
|
|
20
|
+
- @backstage/plugin-events-node@0.4.22-next.0
|
|
21
|
+
- @backstage/plugin-permission-common@0.9.9-next.0
|
|
22
|
+
- @backstage/plugin-permission-node@0.10.13-next.0
|
|
23
|
+
- @backstage/backend-dev-utils@0.1.7
|
|
24
|
+
- @backstage/types@1.2.2
|
|
25
|
+
|
|
26
|
+
## 0.17.0
|
|
27
|
+
|
|
28
|
+
### Minor Changes
|
|
29
|
+
|
|
30
|
+
- c69e03c: Added support for AWS RDS IAM authentication for PostgreSQL connections. Set `connection.type: rds` along with `host`, `user`, and `region` to use short-lived IAM tokens instead of a static password. Requires the `@aws-sdk/rds-signer` package and an IAM role with `rds-db:connect` permission.
|
|
31
|
+
|
|
32
|
+
### Patch Changes
|
|
33
|
+
|
|
34
|
+
- 4559806: Added support for typed `examples` on actions registered via the actions registry. Action authors can now provide examples with compile-time-checked `input` and `output` values that match their schema definitions.
|
|
35
|
+
- 5cd814f: Refactored auditor severity log level mappings to use `zod/v4` with schema-driven defaults and type inference.
|
|
36
|
+
- 482ceed: Migrated from `assertError` to `toError` for error handling.
|
|
37
|
+
- 6e2aaab: Fixed `AwsS3UrlReader` failing to read files from S3 buckets configured with custom endpoint hosts. When an integration was configured with a specific endpoint like `https://bucket-1.s3.eu-central-1.amazonaws.com`, the URL parser incorrectly fell through to the non-AWS code path, always defaulting the region to `us-east-1` instead of extracting it from the hostname.
|
|
38
|
+
- 308c672: `HostDiscovery` now logs a warning when `backend.baseUrl` is set to a localhost address while `NODE_ENV` is `production`, and when `backend.baseUrl` is not a valid URL.
|
|
39
|
+
- 85c5a46: DefaultActionsRegistryService: add json middleware to /.backstage/actions/ routes only
|
|
40
|
+
- 547258f: Refactored the database creation retry loop to avoid an unnecessary delay after the final failed attempt.
|
|
41
|
+
- 79453c0: Updated dependency `wait-for-expect` to `^4.0.0`.
|
|
42
|
+
- f14df56: Added experimental support for using `embedded-postgres` as the database for local development. Set `backend.database.client` to `embedded-postgres` in your app config to enable this. The `embedded-postgres` package must be installed as an explicit dependency in your project.
|
|
43
|
+
- Updated dependencies
|
|
44
|
+
- @backstage/backend-plugin-api@1.9.0
|
|
45
|
+
- @backstage/errors@1.3.0
|
|
46
|
+
- @backstage/plugin-auth-node@0.7.0
|
|
47
|
+
- @backstage/backend-app-api@1.6.1
|
|
48
|
+
- @backstage/cli-node@0.3.1
|
|
49
|
+
- @backstage/config-loader@1.10.10
|
|
50
|
+
- @backstage/integration@2.0.1
|
|
51
|
+
- @backstage/plugin-permission-node@0.10.12
|
|
52
|
+
- @backstage/config@1.3.7
|
|
53
|
+
- @backstage/integration-aws-node@0.1.21
|
|
54
|
+
- @backstage/plugin-events-node@0.4.21
|
|
55
|
+
- @backstage/plugin-permission-common@0.9.8
|
|
56
|
+
|
|
3
57
|
## 0.16.1-next.2
|
|
4
58
|
|
|
5
59
|
### Patch Changes
|
package/config.d.ts
CHANGED
|
@@ -632,6 +632,35 @@ export interface Config {
|
|
|
632
632
|
*/
|
|
633
633
|
ipAddressType?: 'PUBLIC' | 'PRIVATE' | 'PSC';
|
|
634
634
|
}
|
|
635
|
+
| {
|
|
636
|
+
/**
|
|
637
|
+
* The specific config for AWS RDS connections with IAM authentication.
|
|
638
|
+
* Requires the `@aws-sdk/rds-signer` package to be installed.
|
|
639
|
+
* The IAM role or user must have the `rds-db:connect` permission for the database user.
|
|
640
|
+
*/
|
|
641
|
+
type: 'rds';
|
|
642
|
+
/**
|
|
643
|
+
* The hostname of the RDS instance.
|
|
644
|
+
*/
|
|
645
|
+
host: string;
|
|
646
|
+
/**
|
|
647
|
+
* The port number the database is listening on.
|
|
648
|
+
*/
|
|
649
|
+
port: number;
|
|
650
|
+
/**
|
|
651
|
+
* The database user to authenticate as. This user must have the `rds_iam` role granted.
|
|
652
|
+
*/
|
|
653
|
+
user: string;
|
|
654
|
+
/**
|
|
655
|
+
* The AWS region where the RDS instance is located.
|
|
656
|
+
* Falls back to the AWS_REGION or AWS_DEFAULT_REGION environment variables if not set.
|
|
657
|
+
*/
|
|
658
|
+
region?: string;
|
|
659
|
+
/**
|
|
660
|
+
* Other connection settings
|
|
661
|
+
*/
|
|
662
|
+
[key: string]: unknown;
|
|
663
|
+
}
|
|
635
664
|
| {
|
|
636
665
|
/**
|
|
637
666
|
* The rest config for default, regular connections
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CreateBackend.cjs.js","sources":["../src/CreateBackend.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 { Backend, createSpecializedBackend } from '@backstage/backend-app-api';\nimport { auditorServiceFactory } from '@backstage/backend-defaults/auditor';\nimport { authServiceFactory } from '@backstage/backend-defaults/auth';\nimport { cacheServiceFactory } from '@backstage/backend-defaults/cache';\nimport { databaseServiceFactory } from '@backstage/backend-defaults/database';\nimport { discoveryServiceFactory } from '@backstage/backend-defaults/discovery';\nimport { httpAuthServiceFactory } from '@backstage/backend-defaults/httpAuth';\nimport { httpRouterServiceFactory } from '@backstage/backend-defaults/httpRouter';\nimport { lifecycleServiceFactory } from '@backstage/backend-defaults/lifecycle';\nimport { loggerServiceFactory } from '@backstage/backend-defaults/logger';\nimport { permissionsServiceFactory } from '@backstage/backend-defaults/permissions';\nimport { permissionsRegistryServiceFactory } from '@backstage/backend-defaults/permissionsRegistry';\nimport { rootConfigServiceFactory } from '@backstage/backend-defaults/rootConfig';\nimport { rootHealthServiceFactory } from '@backstage/backend-defaults/rootHealth';\nimport { rootHttpRouterServiceFactory } from '@backstage/backend-defaults/rootHttpRouter';\nimport { rootLifecycleServiceFactory } from '@backstage/backend-defaults/rootLifecycle';\nimport { rootLoggerServiceFactory } from '@backstage/backend-defaults/rootLogger';\nimport { schedulerServiceFactory } from '@backstage/backend-defaults/scheduler';\nimport { urlReaderServiceFactory } from '@backstage/backend-defaults/urlReader';\nimport { userInfoServiceFactory } from '@backstage/backend-defaults/userInfo';\nimport { eventsServiceFactory } from '@backstage/plugin-events-node';\nimport {\n actionsRegistryServiceFactory,\n actionsServiceFactory,\n metricsServiceFactory,\n} from '@backstage/backend-defaults/alpha';\nimport { instanceMetadataServiceFactory } from './alpha/entrypoints/instanceMetadata/instanceMetadataServiceFactory';\n\nexport const defaultServiceFactories = [\n auditorServiceFactory,\n authServiceFactory,\n cacheServiceFactory,\n rootConfigServiceFactory,\n databaseServiceFactory,\n discoveryServiceFactory,\n httpAuthServiceFactory,\n httpRouterServiceFactory,\n lifecycleServiceFactory,\n loggerServiceFactory,\n permissionsServiceFactory,\n permissionsRegistryServiceFactory,\n rootHealthServiceFactory,\n rootHttpRouterServiceFactory,\n rootLifecycleServiceFactory,\n rootLoggerServiceFactory,\n schedulerServiceFactory,\n userInfoServiceFactory,\n urlReaderServiceFactory,\n eventsServiceFactory,\n\n // alpha services\n actionsRegistryServiceFactory,\n actionsServiceFactory,\n metricsServiceFactory,\n\n // Unexported alpha services kept around for compatibility reasons\n instanceMetadataServiceFactory,\n];\n\n/**\n * @public\n */\nexport function createBackend(): Backend {\n return createSpecializedBackend({ defaultServiceFactories });\n}\n"],"names":["auditorServiceFactory","authServiceFactory","cacheServiceFactory","rootConfigServiceFactory","databaseServiceFactory","discoveryServiceFactory","httpAuthServiceFactory","httpRouterServiceFactory","lifecycleServiceFactory","loggerServiceFactory","permissionsServiceFactory","permissionsRegistryServiceFactory","rootHealthServiceFactory","rootHttpRouterServiceFactory","rootLifecycleServiceFactory","rootLoggerServiceFactory","schedulerServiceFactory","userInfoServiceFactory","urlReaderServiceFactory","eventsServiceFactory","actionsRegistryServiceFactory","actionsServiceFactory","metricsServiceFactory","instanceMetadataServiceFactory","createSpecializedBackend"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"CreateBackend.cjs.js","sources":["../src/CreateBackend.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 { Backend, createSpecializedBackend } from '@backstage/backend-app-api';\nimport { ServiceFactory } from '@backstage/backend-plugin-api';\nimport { auditorServiceFactory } from '@backstage/backend-defaults/auditor';\nimport { authServiceFactory } from '@backstage/backend-defaults/auth';\nimport { cacheServiceFactory } from '@backstage/backend-defaults/cache';\nimport { databaseServiceFactory } from '@backstage/backend-defaults/database';\nimport { discoveryServiceFactory } from '@backstage/backend-defaults/discovery';\nimport { httpAuthServiceFactory } from '@backstage/backend-defaults/httpAuth';\nimport { httpRouterServiceFactory } from '@backstage/backend-defaults/httpRouter';\nimport { lifecycleServiceFactory } from '@backstage/backend-defaults/lifecycle';\nimport { loggerServiceFactory } from '@backstage/backend-defaults/logger';\nimport { permissionsServiceFactory } from '@backstage/backend-defaults/permissions';\nimport { permissionsRegistryServiceFactory } from '@backstage/backend-defaults/permissionsRegistry';\nimport { rootConfigServiceFactory } from '@backstage/backend-defaults/rootConfig';\nimport { rootHealthServiceFactory } from '@backstage/backend-defaults/rootHealth';\nimport { rootHttpRouterServiceFactory } from '@backstage/backend-defaults/rootHttpRouter';\nimport { rootLifecycleServiceFactory } from '@backstage/backend-defaults/rootLifecycle';\nimport { rootLoggerServiceFactory } from '@backstage/backend-defaults/rootLogger';\nimport { schedulerServiceFactory } from '@backstage/backend-defaults/scheduler';\nimport { urlReaderServiceFactory } from '@backstage/backend-defaults/urlReader';\nimport { userInfoServiceFactory } from '@backstage/backend-defaults/userInfo';\nimport { eventsServiceFactory } from '@backstage/plugin-events-node';\nimport {\n actionsRegistryServiceFactory,\n actionsServiceFactory,\n metricsServiceFactory,\n} from '@backstage/backend-defaults/alpha';\nimport { instanceMetadataServiceFactory } from './alpha/entrypoints/instanceMetadata/instanceMetadataServiceFactory';\n\n/** @public */\nexport const defaultServiceFactories: ServiceFactory[] = [\n auditorServiceFactory,\n authServiceFactory,\n cacheServiceFactory,\n rootConfigServiceFactory,\n databaseServiceFactory,\n discoveryServiceFactory,\n httpAuthServiceFactory,\n httpRouterServiceFactory,\n lifecycleServiceFactory,\n loggerServiceFactory,\n permissionsServiceFactory,\n permissionsRegistryServiceFactory,\n rootHealthServiceFactory,\n rootHttpRouterServiceFactory,\n rootLifecycleServiceFactory,\n rootLoggerServiceFactory,\n schedulerServiceFactory,\n userInfoServiceFactory,\n urlReaderServiceFactory,\n eventsServiceFactory,\n\n // alpha services\n actionsRegistryServiceFactory,\n actionsServiceFactory,\n metricsServiceFactory,\n\n // Unexported alpha services kept around for compatibility reasons\n instanceMetadataServiceFactory,\n];\n\n/**\n * @public\n */\nexport function createBackend(): Backend {\n return createSpecializedBackend({ defaultServiceFactories });\n}\n"],"names":["auditorServiceFactory","authServiceFactory","cacheServiceFactory","rootConfigServiceFactory","databaseServiceFactory","discoveryServiceFactory","httpAuthServiceFactory","httpRouterServiceFactory","lifecycleServiceFactory","loggerServiceFactory","permissionsServiceFactory","permissionsRegistryServiceFactory","rootHealthServiceFactory","rootHttpRouterServiceFactory","rootLifecycleServiceFactory","rootLoggerServiceFactory","schedulerServiceFactory","userInfoServiceFactory","urlReaderServiceFactory","eventsServiceFactory","actionsRegistryServiceFactory","actionsServiceFactory","metricsServiceFactory","instanceMetadataServiceFactory","createSpecializedBackend"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA8CO,MAAM,uBAAA,GAA4C;AAAA,EACvDA,6BAAA;AAAA,EACAC,uBAAA;AAAA,EACAC,yBAAA;AAAA,EACAC,mCAAA;AAAA,EACAC,+BAAA;AAAA,EACAC,iCAAA;AAAA,EACAC,+BAAA;AAAA,EACAC,mCAAA;AAAA,EACAC,iCAAA;AAAA,EACAC,2BAAA;AAAA,EACAC,qCAAA;AAAA,EACAC,qDAAA;AAAA,EACAC,mCAAA;AAAA,EACAC,2CAAA;AAAA,EACAC,yCAAA;AAAA,EACAC,mCAAA;AAAA,EACAC,iCAAA;AAAA,EACAC,+BAAA;AAAA,EACAC,iCAAA;AAAA,EACAC,qCAAA;AAAA;AAAA,EAGAC,mCAAA;AAAA,EACAC,2BAAA;AAAA,EACAC,2BAAA;AAAA;AAAA,EAGAC;AACF;AAKO,SAAS,aAAA,GAAyB;AACvC,EAAA,OAAOC,sCAAA,CAAyB,EAAE,uBAAA,EAAyB,CAAA;AAC7D;;;;;"}
|
|
@@ -61,6 +61,8 @@ async function buildPgDatabaseConfig(dbConfig, overrides) {
|
|
|
61
61
|
return buildAzurePgConfig(mergedConfigReader);
|
|
62
62
|
case "cloudsql":
|
|
63
63
|
return buildCloudSqlConfig(mergedConfigReader);
|
|
64
|
+
case "rds":
|
|
65
|
+
return buildRdsPgConfig(mergedConfigReader);
|
|
64
66
|
default:
|
|
65
67
|
throw new Error(`Unknown connection type: ${config$1.connection.type}`);
|
|
66
68
|
}
|
|
@@ -166,6 +168,56 @@ async function buildCloudSqlConfig(config) {
|
|
|
166
168
|
}
|
|
167
169
|
};
|
|
168
170
|
}
|
|
171
|
+
async function buildRdsPgConfig(config) {
|
|
172
|
+
const { Signer } = require("@aws-sdk/rds-signer");
|
|
173
|
+
let hostname;
|
|
174
|
+
let port;
|
|
175
|
+
let username;
|
|
176
|
+
try {
|
|
177
|
+
hostname = config.getString("connection.host");
|
|
178
|
+
port = config.getNumber("connection.port");
|
|
179
|
+
username = config.getString("connection.user");
|
|
180
|
+
} catch (err) {
|
|
181
|
+
throw new errors.ForwardedError(
|
|
182
|
+
"AWS RDS IAM auth: missing required database connection config \u2014 make sure connection.host, connection.port, and connection.user are set and any environment variables they reference are set",
|
|
183
|
+
err
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
const region = config.getOptionalString("connection.region") ?? process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION;
|
|
187
|
+
if (!region) {
|
|
188
|
+
throw new Error(
|
|
189
|
+
"Missing region for AWS RDS IAM auth: set connection.region or the AWS_REGION environment variable"
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
const rawConfig = config.get();
|
|
193
|
+
const sanitizedConnection = lodash.omit(
|
|
194
|
+
config.get("connection"),
|
|
195
|
+
["type", "region"]
|
|
196
|
+
);
|
|
197
|
+
const signer = new Signer({ hostname, port, username, region });
|
|
198
|
+
const tokenTtlMs = 15 * 60 * 1e3;
|
|
199
|
+
const renewalOffsetMs = 60 * 1e3;
|
|
200
|
+
async function getConnectionConfig() {
|
|
201
|
+
try {
|
|
202
|
+
const password = await signer.getAuthToken();
|
|
203
|
+
const tokenExpiration = Date.now() + tokenTtlMs - renewalOffsetMs;
|
|
204
|
+
return {
|
|
205
|
+
...sanitizedConnection,
|
|
206
|
+
password,
|
|
207
|
+
expirationChecker: () => tokenExpiration <= Date.now()
|
|
208
|
+
};
|
|
209
|
+
} catch (err) {
|
|
210
|
+
throw new errors.ForwardedError(
|
|
211
|
+
`AWS RDS IAM auth token acquisition failed for ${username}@${hostname}:${port}`,
|
|
212
|
+
err
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return {
|
|
217
|
+
...rawConfig,
|
|
218
|
+
connection: getConnectionConfig
|
|
219
|
+
};
|
|
220
|
+
}
|
|
169
221
|
function getPgConnectionConfig(dbConfig, parseConnectionString) {
|
|
170
222
|
const connection = dbConfig.get("connection");
|
|
171
223
|
const isConnectionString = typeof connection === "string" || connection instanceof String;
|
|
@@ -185,40 +237,43 @@ function requirePgConnectionString() {
|
|
|
185
237
|
}
|
|
186
238
|
}
|
|
187
239
|
async function ensurePgDatabaseExists(dbConfig, ...databases) {
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
240
|
+
const ensureDatabase = async (database) => {
|
|
241
|
+
const admin = await createPgDatabaseClient(dbConfig, {
|
|
242
|
+
connection: {
|
|
243
|
+
database: "postgres"
|
|
244
|
+
},
|
|
245
|
+
pool: {
|
|
246
|
+
min: 0,
|
|
247
|
+
max: 1,
|
|
248
|
+
acquireTimeoutMillis: 1e4
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
try {
|
|
199
252
|
const result = await admin.from("pg_database").where("datname", database).count();
|
|
200
253
|
if (parseInt(result[0].count, 10) > 0) {
|
|
201
254
|
return;
|
|
202
255
|
}
|
|
203
256
|
await admin.raw(`CREATE DATABASE ??`, [database]);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
257
|
+
} finally {
|
|
258
|
+
await admin.destroy();
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
await Promise.all(
|
|
262
|
+
databases.map(async (database) => {
|
|
263
|
+
const maxAttempts = 3;
|
|
264
|
+
for (let attempt = 1; ; attempt++) {
|
|
265
|
+
try {
|
|
266
|
+
return await ddlLimiter(() => ensureDatabase(database));
|
|
267
|
+
} catch (err) {
|
|
268
|
+
if (attempt >= maxAttempts) {
|
|
269
|
+
throw err;
|
|
270
|
+
} else {
|
|
271
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
213
272
|
}
|
|
214
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
215
273
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
} finally {
|
|
220
|
-
await admin.destroy();
|
|
221
|
-
}
|
|
274
|
+
}
|
|
275
|
+
})
|
|
276
|
+
);
|
|
222
277
|
}
|
|
223
278
|
async function ensurePgSchemaExists(dbConfig, ...schemas) {
|
|
224
279
|
const admin = await createPgDatabaseClient(dbConfig);
|
|
@@ -365,6 +420,7 @@ exports.PgConnector = PgConnector;
|
|
|
365
420
|
exports.buildAzurePgConfig = buildAzurePgConfig;
|
|
366
421
|
exports.buildCloudSqlConfig = buildCloudSqlConfig;
|
|
367
422
|
exports.buildPgDatabaseConfig = buildPgDatabaseConfig;
|
|
423
|
+
exports.buildRdsPgConfig = buildRdsPgConfig;
|
|
368
424
|
exports.computePgPluginConfig = computePgPluginConfig;
|
|
369
425
|
exports.createPgDatabaseClient = createPgDatabaseClient;
|
|
370
426
|
exports.ensurePgDatabaseExists = ensurePgDatabaseExists;
|
|
@@ -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 {\n Config,\n ConfigReader,\n readDurationFromConfig,\n} from '@backstage/config';\nimport { ForwardedError } from '@backstage/errors';\nimport {\n durationToMilliseconds,\n HumanDuration,\n JsonObject,\n} 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 { mergeDatabaseConfig } from './mergeDatabaseConfig';\nimport format from 'pg-format';\nimport { TokenCredential } from '@azure/identity';\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 async function createPgDatabaseClient(\n dbConfig: Config,\n overrides?: Knex.Config,\n) {\n const knexConfig = await 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 async function buildPgDatabaseConfig(\n dbConfig: Config,\n overrides?: Knex.Config,\n) {\n const config = mergeDatabaseConfig(\n dbConfig.get(),\n {\n connection: getPgConnectionConfig(dbConfig, !!overrides),\n useNullAsDefault: true,\n },\n overrides,\n );\n const mergedConfigReader = new ConfigReader(config);\n\n if (config.connection.type === 'default' || !config.connection.type) {\n const connectionValue = config.connection;\n const sanitizedConnection =\n typeof connectionValue === 'string' || connectionValue instanceof String\n ? connectionValue\n : // connection is an object, omit config-only props\n omit(connectionValue as Record<string, unknown>, [\n 'type',\n 'instance',\n 'tokenCredential',\n ]);\n\n return {\n ...config,\n connection: sanitizedConnection,\n };\n }\n\n switch (config.connection.type) {\n case 'azure':\n return buildAzurePgConfig(mergedConfigReader);\n case 'cloudsql':\n return buildCloudSqlConfig(mergedConfigReader);\n default:\n throw new Error(`Unknown connection type: ${config.connection.type}`);\n }\n}\n\n/* Note: the following type definition is intentionally duplicated in\n * /packages/backend-defaults/config.d.ts so the clientSecret property\n * can be annotated with \"@visibility secret\" there.\n */\nexport type AzureTokenCredentialConfig = {\n /**\n * How early before an access token expires to refresh it with a new one.\n * Defaults to 5 minutes\n * Supported formats:\n * - A string in the format of '1d', '2 seconds' etc. as supported by the `ms`\n * library.\n * - A standard ISO formatted duration string, e.g. 'P2DT6H' or 'PT1M'.\n * - An object with individual units (in plural) as keys, e.g. `{ days: 2, hours: 6 }`.\n */\n tokenRenewableOffsetTime?: string | HumanDuration;\n /**\n * The client ID of a user-assigned managed identity.\n * If not provided, the system-assigned managed identity is used.\n */\n clientId?: string;\n clientSecret?: string;\n tenantId?: string;\n};\n\nexport async function buildAzurePgConfig(config: Config): Promise<Knex.Config> {\n const {\n DefaultAzureCredential,\n ManagedIdentityCredential,\n ClientSecretCredential,\n } = require('@azure/identity');\n\n const tokenConfig = config.getOptionalConfig('connection.tokenCredential');\n\n const tokenRenewableOffsetTime = durationToMilliseconds(\n tokenConfig?.has('tokenRenewableOffsetTime')\n ? readDurationFromConfig(tokenConfig, { key: 'tokenRenewableOffsetTime' })\n : { minutes: 5 },\n );\n\n const clientId = tokenConfig?.getOptionalString('clientId');\n const tenantId = tokenConfig?.getOptionalString('tenantId');\n const clientSecret = tokenConfig?.getOptionalString('clientSecret');\n let credential: TokenCredential;\n\n /**\n * Determine which TokenCredential to use based on provided config\n * 1. If clientId, tenantId and clientSecret are provided, use ClientSecretCredential\n * 2. If only clientId is provided, use ManagedIdentityCredential with user-assigned identity\n * 3. Otherwise, use DefaultAzureCredential (which may use system-assigned identity among other methods)\n */\n if (clientId && tenantId && clientSecret) {\n credential = new ClientSecretCredential(tenantId, clientId, clientSecret);\n } else if (clientId) {\n credential = new ManagedIdentityCredential(clientId);\n } else {\n credential = new DefaultAzureCredential();\n }\n\n const rawConfig = config.get() as Record<string, unknown>;\n\n const normalized = normalizeConnection(rawConfig.connection as any);\n const sanitizedConnection = omit(normalized, [\n 'type',\n 'instance',\n 'tokenCredential',\n ]) as Partial<Knex.StaticConnectionConfig>;\n\n async function getConnectionConfig() {\n const token = await credential.getToken(\n 'https://ossrdbms-aad.database.windows.net/.default',\n );\n\n if (!token) {\n throw new Error(\n 'Failed to acquire Azure access token for database authentication',\n );\n }\n\n const connectionConfig = {\n ...sanitizedConnection,\n password: token.token,\n expirationChecker: () =>\n /* return true if the token is within the renewable offset time */\n token.expiresOnTimestamp - tokenRenewableOffsetTime <= Date.now(),\n };\n\n return connectionConfig;\n }\n\n return {\n ...(rawConfig as Record<string, unknown>),\n connection: getConnectionConfig,\n };\n}\n\nexport async function buildCloudSqlConfig(\n config: Config,\n): Promise<Knex.Config> {\n const client = config.getOptionalString('client');\n\n if (client && client !== 'pg') {\n throw new Error('Cloud SQL only supports the pg client');\n }\n\n const instance = config.getOptionalString('connection.instance');\n if (!instance) {\n throw new Error('Missing instance connection name for Cloud SQL');\n }\n\n const {\n Connector: CloudSqlConnector,\n IpAddressTypes,\n AuthTypes,\n } = require('@google-cloud/cloud-sql-connector') as typeof import('@google-cloud/cloud-sql-connector');\n const connector = new CloudSqlConnector();\n\n type IpType = (typeof IpAddressTypes)[keyof typeof IpAddressTypes];\n const ipTypeRaw = config.getOptionalString('connection.ipAddressType');\n\n let ipType: IpType | undefined;\n if (ipTypeRaw !== undefined) {\n if (\n !(Object.values(IpAddressTypes) as Array<string | number>).includes(\n ipTypeRaw as any,\n )\n ) {\n throw new Error(\n `Invalid connection.ipAddressType: ${ipTypeRaw}; valid values: ${Object.values(\n IpAddressTypes,\n ).join(', ')}`,\n );\n }\n ipType = ipTypeRaw as unknown as IpType;\n }\n\n const clientOpts = await connector.getOptions({\n instanceConnectionName: instance,\n ipType: ipType ?? IpAddressTypes.PUBLIC,\n authType: AuthTypes.IAM,\n });\n\n const rawConfig = config.get() as Record<string, unknown>;\n const normalized = normalizeConnection(rawConfig.connection as any);\n const sanitizedConnection = omit(normalized, [\n 'type',\n 'instance',\n ]) as Partial<Knex.StaticConnectionConfig>;\n\n return {\n ...(rawConfig as Record<string, unknown>),\n client: 'pg',\n connection: {\n ...sanitizedConnection,\n ...clientOpts,\n },\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 = await 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 = await 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 = await 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\n/**\n * The computed configuration for a plugin's postgres database connection.\n */\nexport interface PgPluginDatabaseConfig {\n /** The database client type (e.g. 'pg') */\n client: string;\n /** Whether the client type was overridden at the plugin level */\n clientOverridden: boolean;\n /** The optional role to set on connections */\n role: string | undefined;\n /** Additional knex configuration merged from base and plugin config */\n additionalKnexConfig: JsonObject | undefined;\n /** Whether to ensure the database exists */\n ensureExists: boolean;\n /** Whether to ensure the schema exists */\n ensureSchemaExists: boolean;\n /** The plugin division mode ('database' or 'schema') */\n pluginDivisionMode: string;\n /** The connection configuration */\n connection: Knex.PgConnectionConfig;\n /** The database name, if any */\n databaseName: string | undefined;\n /** Database client overrides including schema overrides if applicable */\n databaseClientOverrides: Knex.Config;\n /** The full knex config for the plugin */\n knexConfig: Knex.Config;\n}\n\n/**\n * Computes all postgres database configuration for a plugin from the provided config.\n *\n * @param config - The database config object\n * @param pluginId - The plugin ID to compute config for\n * @param prefix - The database name prefix (e.g. 'backstage_plugin_')\n * @returns All computed configuration values for the plugin\n */\nexport function computePgPluginConfig(\n config: Config,\n pluginId: string,\n prefix: string,\n): PgPluginDatabaseConfig {\n // Client type\n const pluginClient = config.getOptionalString(\n `${pluginPath(pluginId)}.client`,\n );\n const baseClient = config.getString('client');\n const client = pluginClient ?? baseClient;\n const clientOverridden = client !== baseClient;\n\n // Role\n const role =\n config.getOptionalString(`${pluginPath(pluginId)}.role`) ??\n config.getOptionalString('role');\n\n // Additional knex config\n const pluginKnexConfig = config\n .getOptionalConfig(`${pluginPath(pluginId)}.knexConfig`)\n ?.get<JsonObject>();\n const baseKnexConfig = config\n .getOptionalConfig('knexConfig')\n ?.get<JsonObject>();\n const additionalKnexConfig = merge(baseKnexConfig, pluginKnexConfig);\n\n // Ensure exists flags\n const baseEnsureExists = config.getOptionalBoolean('ensureExists') ?? true;\n const ensureExists =\n config.getOptionalBoolean(`${pluginPath(pluginId)}.ensureExists`) ??\n baseEnsureExists;\n\n const baseEnsureSchemaExists =\n config.getOptionalBoolean('ensureSchemaExists') ?? false;\n const ensureSchemaExists =\n config.getOptionalBoolean(\n `${pluginPath(pluginId)}.getEnsureSchemaExistsConfig`,\n ) ?? baseEnsureSchemaExists;\n\n // Plugin division mode\n const pluginDivisionMode =\n config.getOptionalString('pluginDivisionMode') ?? 'database';\n\n // Connection config\n let baseConnection = normalizeConnection(config.get('connection'));\n\n // Databases cannot be shared unless the `pluginDivisionMode` is set to `schema`.\n // The `database` property from the base connection is omitted unless\n // `pluginDivisionMode` is set to `schema`.\n if (pluginDivisionMode !== 'schema') {\n baseConnection = omit(baseConnection, 'database');\n }\n\n // Get and normalize optional plugin specific database connection\n const pluginConnection = normalizeConnection(\n config.getOptional(`${pluginPath(pluginId)}.connection`),\n );\n\n (\n baseConnection as Knex.PgConnectionConfig\n ).application_name ||= `backstage_plugin_${pluginId}`;\n\n const connection = {\n // Include base connection if client type has not been overridden\n ...(clientOverridden ? {} : baseConnection),\n ...pluginConnection,\n } as Knex.PgConnectionConfig;\n\n // Database name\n const connectionDatabaseName = (connection as Knex.ConnectionConfig)\n ?.database;\n let databaseName: string | undefined;\n\n if (pluginDivisionMode === 'schema') {\n // `pluginDivisionMode` as `schema` should use overridden databaseName if supplied\n // or fallback to default knex database\n databaseName = connectionDatabaseName;\n } else {\n // All other supported databases should fallback to an auto-prefixed name\n databaseName = connectionDatabaseName ?? `${prefix}${pluginId}`;\n }\n\n // Database client overrides\n let databaseClientOverrides: Knex.Config = {};\n if (databaseName) {\n databaseClientOverrides = { connection: { database: databaseName } };\n }\n if (pluginDivisionMode === 'schema') {\n databaseClientOverrides = mergeDatabaseConfig({}, databaseClientOverrides, {\n searchPath: [pluginId],\n });\n }\n\n // Full knex config for plugin\n const knexConfig: Knex.Config = {\n ...additionalKnexConfig,\n client,\n connection,\n ...(role && { role }),\n };\n\n return {\n client,\n clientOverridden,\n role,\n additionalKnexConfig,\n ensureExists,\n ensureSchemaExists,\n pluginDivisionMode,\n connection,\n databaseName,\n databaseClientOverrides,\n knexConfig,\n };\n}\n\nexport class PgConnector implements Connector {\n private readonly config: Config;\n private readonly prefix: string;\n\n constructor(config: Config, prefix: string) {\n this.config = config;\n this.prefix = prefix;\n }\n\n async getClient(\n pluginId: string,\n _deps: {\n logger: LoggerService;\n lifecycle: LifecycleService;\n },\n ): Promise<Knex> {\n const pluginDbConfig = computePgPluginConfig(\n this.config,\n pluginId,\n this.prefix,\n );\n\n if (pluginDbConfig.databaseName && pluginDbConfig.ensureExists) {\n try {\n await ensurePgDatabaseExists(this.config, pluginDbConfig.databaseName);\n } catch (error) {\n throw new Error(\n `Failed to connect to the database to make sure that '${pluginDbConfig.databaseName}' exists, ${error}`,\n );\n }\n }\n\n if (pluginDbConfig.pluginDivisionMode === 'schema') {\n if (pluginDbConfig.ensureSchemaExists || pluginDbConfig.ensureExists) {\n try {\n await ensurePgSchemaExists(this.config, 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 client = createPgDatabaseClient(\n this.config,\n mergeDatabaseConfig(\n pluginDbConfig.knexConfig,\n pluginDbConfig.databaseClientOverrides,\n ),\n );\n\n return client;\n }\n}\n"],"names":["limiterFactory","knexFactory","format","config","mergeDatabaseConfig","ConfigReader","omit","durationToMilliseconds","readDurationFromConfig","ForwardedError","merge"],"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 {\n Config,\n ConfigReader,\n readDurationFromConfig,\n} from '@backstage/config';\nimport { ForwardedError } from '@backstage/errors';\nimport {\n durationToMilliseconds,\n HumanDuration,\n JsonObject,\n} 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 { mergeDatabaseConfig } from './mergeDatabaseConfig';\nimport format from 'pg-format';\nimport { TokenCredential } from '@azure/identity';\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 async function createPgDatabaseClient(\n dbConfig: Config,\n overrides?: Knex.Config,\n) {\n const knexConfig = await 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 async function buildPgDatabaseConfig(\n dbConfig: Config,\n overrides?: Knex.Config,\n) {\n const config = mergeDatabaseConfig(\n dbConfig.get(),\n {\n connection: getPgConnectionConfig(dbConfig, !!overrides),\n useNullAsDefault: true,\n },\n overrides,\n );\n const mergedConfigReader = new ConfigReader(config);\n\n if (config.connection.type === 'default' || !config.connection.type) {\n const connectionValue = config.connection;\n const sanitizedConnection =\n typeof connectionValue === 'string' || connectionValue instanceof String\n ? connectionValue\n : // connection is an object, omit config-only props\n omit(connectionValue as Record<string, unknown>, [\n 'type',\n 'instance',\n 'tokenCredential',\n ]);\n\n return {\n ...config,\n connection: sanitizedConnection,\n };\n }\n\n switch (config.connection.type) {\n case 'azure':\n return buildAzurePgConfig(mergedConfigReader);\n case 'cloudsql':\n return buildCloudSqlConfig(mergedConfigReader);\n case 'rds':\n return buildRdsPgConfig(mergedConfigReader);\n default:\n throw new Error(`Unknown connection type: ${config.connection.type}`);\n }\n}\n\n/* Note: the following type definition is intentionally duplicated in\n * /packages/backend-defaults/config.d.ts so the clientSecret property\n * can be annotated with \"@visibility secret\" there.\n */\nexport type AzureTokenCredentialConfig = {\n /**\n * How early before an access token expires to refresh it with a new one.\n * Defaults to 5 minutes\n * Supported formats:\n * - A string in the format of '1d', '2 seconds' etc. as supported by the `ms`\n * library.\n * - A standard ISO formatted duration string, e.g. 'P2DT6H' or 'PT1M'.\n * - An object with individual units (in plural) as keys, e.g. `{ days: 2, hours: 6 }`.\n */\n tokenRenewableOffsetTime?: string | HumanDuration;\n /**\n * The client ID of a user-assigned managed identity.\n * If not provided, the system-assigned managed identity is used.\n */\n clientId?: string;\n clientSecret?: string;\n tenantId?: string;\n};\n\nexport async function buildAzurePgConfig(config: Config): Promise<Knex.Config> {\n const {\n DefaultAzureCredential,\n ManagedIdentityCredential,\n ClientSecretCredential,\n } = require('@azure/identity');\n\n const tokenConfig = config.getOptionalConfig('connection.tokenCredential');\n\n const tokenRenewableOffsetTime = durationToMilliseconds(\n tokenConfig?.has('tokenRenewableOffsetTime')\n ? readDurationFromConfig(tokenConfig, { key: 'tokenRenewableOffsetTime' })\n : { minutes: 5 },\n );\n\n const clientId = tokenConfig?.getOptionalString('clientId');\n const tenantId = tokenConfig?.getOptionalString('tenantId');\n const clientSecret = tokenConfig?.getOptionalString('clientSecret');\n let credential: TokenCredential;\n\n /**\n * Determine which TokenCredential to use based on provided config\n * 1. If clientId, tenantId and clientSecret are provided, use ClientSecretCredential\n * 2. If only clientId is provided, use ManagedIdentityCredential with user-assigned identity\n * 3. Otherwise, use DefaultAzureCredential (which may use system-assigned identity among other methods)\n */\n if (clientId && tenantId && clientSecret) {\n credential = new ClientSecretCredential(tenantId, clientId, clientSecret);\n } else if (clientId) {\n credential = new ManagedIdentityCredential(clientId);\n } else {\n credential = new DefaultAzureCredential();\n }\n\n const rawConfig = config.get() as Record<string, unknown>;\n\n const normalized = normalizeConnection(rawConfig.connection as any);\n const sanitizedConnection = omit(normalized, [\n 'type',\n 'instance',\n 'tokenCredential',\n ]) as Partial<Knex.StaticConnectionConfig>;\n\n async function getConnectionConfig() {\n const token = await credential.getToken(\n 'https://ossrdbms-aad.database.windows.net/.default',\n );\n\n if (!token) {\n throw new Error(\n 'Failed to acquire Azure access token for database authentication',\n );\n }\n\n const connectionConfig = {\n ...sanitizedConnection,\n password: token.token,\n expirationChecker: () =>\n /* return true if the token is within the renewable offset time */\n token.expiresOnTimestamp - tokenRenewableOffsetTime <= Date.now(),\n };\n\n return connectionConfig;\n }\n\n return {\n ...(rawConfig as Record<string, unknown>),\n connection: getConnectionConfig,\n };\n}\n\nexport async function buildCloudSqlConfig(\n config: Config,\n): Promise<Knex.Config> {\n const client = config.getOptionalString('client');\n\n if (client && client !== 'pg') {\n throw new Error('Cloud SQL only supports the pg client');\n }\n\n const instance = config.getOptionalString('connection.instance');\n if (!instance) {\n throw new Error('Missing instance connection name for Cloud SQL');\n }\n\n const {\n Connector: CloudSqlConnector,\n IpAddressTypes,\n AuthTypes,\n } = require('@google-cloud/cloud-sql-connector') as typeof import('@google-cloud/cloud-sql-connector');\n const connector = new CloudSqlConnector();\n\n type IpType = (typeof IpAddressTypes)[keyof typeof IpAddressTypes];\n const ipTypeRaw = config.getOptionalString('connection.ipAddressType');\n\n let ipType: IpType | undefined;\n if (ipTypeRaw !== undefined) {\n if (\n !(Object.values(IpAddressTypes) as Array<string | number>).includes(\n ipTypeRaw as any,\n )\n ) {\n throw new Error(\n `Invalid connection.ipAddressType: ${ipTypeRaw}; valid values: ${Object.values(\n IpAddressTypes,\n ).join(', ')}`,\n );\n }\n ipType = ipTypeRaw as unknown as IpType;\n }\n\n const clientOpts = await connector.getOptions({\n instanceConnectionName: instance,\n ipType: ipType ?? IpAddressTypes.PUBLIC,\n authType: AuthTypes.IAM,\n });\n\n const rawConfig = config.get() as Record<string, unknown>;\n const normalized = normalizeConnection(rawConfig.connection as any);\n const sanitizedConnection = omit(normalized, [\n 'type',\n 'instance',\n ]) as Partial<Knex.StaticConnectionConfig>;\n\n return {\n ...(rawConfig as Record<string, unknown>),\n client: 'pg',\n connection: {\n ...sanitizedConnection,\n ...clientOpts,\n },\n };\n}\n\nexport async function buildRdsPgConfig(config: Config): Promise<Knex.Config> {\n const { Signer } =\n require('@aws-sdk/rds-signer') as typeof import('@aws-sdk/rds-signer');\n\n let hostname: string;\n let port: number;\n let username: string;\n try {\n hostname = config.getString('connection.host');\n port = config.getNumber('connection.port');\n username = config.getString('connection.user');\n } catch (err) {\n throw new ForwardedError(\n 'AWS RDS IAM auth: missing required database connection config — make sure connection.host, connection.port, and connection.user are set and any environment variables they reference are set',\n err,\n );\n }\n const region =\n config.getOptionalString('connection.region') ??\n process.env.AWS_REGION ??\n process.env.AWS_DEFAULT_REGION;\n if (!region) {\n throw new Error(\n 'Missing region for AWS RDS IAM auth: set connection.region or the AWS_REGION environment variable',\n );\n }\n\n const rawConfig = config.get() as Record<string, unknown>;\n const sanitizedConnection = omit(\n config.get('connection') as Record<string, unknown>,\n ['type', 'region'],\n ) as Partial<Knex.StaticConnectionConfig>;\n\n const signer = new Signer({ hostname, port, username, region });\n\n // RDS IAM auth tokens are valid for 15 minutes. Renew 1 minute early so\n // that pooled connections are refreshed before the token actually expires.\n const tokenTtlMs = 15 * 60 * 1000;\n const renewalOffsetMs = 60 * 1000;\n\n async function getConnectionConfig() {\n try {\n const password = await signer.getAuthToken();\n const tokenExpiration = Date.now() + tokenTtlMs - renewalOffsetMs;\n return {\n ...sanitizedConnection,\n password,\n expirationChecker: () => tokenExpiration <= Date.now(),\n };\n } catch (err) {\n throw new ForwardedError(\n `AWS RDS IAM auth token acquisition failed for ${username}@${hostname}:${port}`,\n err,\n );\n }\n }\n\n return {\n ...(rawConfig as Record<string, unknown>),\n connection: getConnectionConfig,\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 // Implements a single existence check attempt\n const ensureDatabase = async (database: string) => {\n const admin = await createPgDatabaseClient(dbConfig, {\n connection: {\n database: 'postgres',\n },\n pool: {\n min: 0,\n max: 1,\n acquireTimeoutMillis: 10000,\n },\n });\n\n try {\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 } finally {\n await admin.destroy();\n }\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 const maxAttempts = 3;\n for (let attempt = 1; ; attempt++) {\n try {\n return await ddlLimiter(() => ensureDatabase(database));\n } catch (err) {\n if (attempt >= maxAttempts) {\n throw err;\n } else {\n await new Promise(resolve => setTimeout(resolve, 100));\n }\n }\n }\n }),\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 = await 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 = await 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\n/**\n * The computed configuration for a plugin's postgres database connection.\n */\nexport interface PgPluginDatabaseConfig {\n /** The database client type (e.g. 'pg') */\n client: string;\n /** Whether the client type was overridden at the plugin level */\n clientOverridden: boolean;\n /** The optional role to set on connections */\n role: string | undefined;\n /** Additional knex configuration merged from base and plugin config */\n additionalKnexConfig: JsonObject | undefined;\n /** Whether to ensure the database exists */\n ensureExists: boolean;\n /** Whether to ensure the schema exists */\n ensureSchemaExists: boolean;\n /** The plugin division mode ('database' or 'schema') */\n pluginDivisionMode: string;\n /** The connection configuration */\n connection: Knex.PgConnectionConfig;\n /** The database name, if any */\n databaseName: string | undefined;\n /** Database client overrides including schema overrides if applicable */\n databaseClientOverrides: Knex.Config;\n /** The full knex config for the plugin */\n knexConfig: Knex.Config;\n}\n\n/**\n * Computes all postgres database configuration for a plugin from the provided config.\n *\n * @param config - The database config object\n * @param pluginId - The plugin ID to compute config for\n * @param prefix - The database name prefix (e.g. 'backstage_plugin_')\n * @returns All computed configuration values for the plugin\n */\nexport function computePgPluginConfig(\n config: Config,\n pluginId: string,\n prefix: string,\n): PgPluginDatabaseConfig {\n // Client type\n const pluginClient = config.getOptionalString(\n `${pluginPath(pluginId)}.client`,\n );\n const baseClient = config.getString('client');\n const client = pluginClient ?? baseClient;\n const clientOverridden = client !== baseClient;\n\n // Role\n const role =\n config.getOptionalString(`${pluginPath(pluginId)}.role`) ??\n config.getOptionalString('role');\n\n // Additional knex config\n const pluginKnexConfig = config\n .getOptionalConfig(`${pluginPath(pluginId)}.knexConfig`)\n ?.get<JsonObject>();\n const baseKnexConfig = config\n .getOptionalConfig('knexConfig')\n ?.get<JsonObject>();\n const additionalKnexConfig = merge(baseKnexConfig, pluginKnexConfig);\n\n // Ensure exists flags\n const baseEnsureExists = config.getOptionalBoolean('ensureExists') ?? true;\n const ensureExists =\n config.getOptionalBoolean(`${pluginPath(pluginId)}.ensureExists`) ??\n baseEnsureExists;\n\n const baseEnsureSchemaExists =\n config.getOptionalBoolean('ensureSchemaExists') ?? false;\n const ensureSchemaExists =\n config.getOptionalBoolean(\n `${pluginPath(pluginId)}.getEnsureSchemaExistsConfig`,\n ) ?? baseEnsureSchemaExists;\n\n // Plugin division mode\n const pluginDivisionMode =\n config.getOptionalString('pluginDivisionMode') ?? 'database';\n\n // Connection config\n let baseConnection = normalizeConnection(config.get('connection'));\n\n // Databases cannot be shared unless the `pluginDivisionMode` is set to `schema`.\n // The `database` property from the base connection is omitted unless\n // `pluginDivisionMode` is set to `schema`.\n if (pluginDivisionMode !== 'schema') {\n baseConnection = omit(baseConnection, 'database');\n }\n\n // Get and normalize optional plugin specific database connection\n const pluginConnection = normalizeConnection(\n config.getOptional(`${pluginPath(pluginId)}.connection`),\n );\n\n (\n baseConnection as Knex.PgConnectionConfig\n ).application_name ||= `backstage_plugin_${pluginId}`;\n\n const connection = {\n // Include base connection if client type has not been overridden\n ...(clientOverridden ? {} : baseConnection),\n ...pluginConnection,\n } as Knex.PgConnectionConfig;\n\n // Database name\n const connectionDatabaseName = (connection as Knex.ConnectionConfig)\n ?.database;\n let databaseName: string | undefined;\n\n if (pluginDivisionMode === 'schema') {\n // `pluginDivisionMode` as `schema` should use overridden databaseName if supplied\n // or fallback to default knex database\n databaseName = connectionDatabaseName;\n } else {\n // All other supported databases should fallback to an auto-prefixed name\n databaseName = connectionDatabaseName ?? `${prefix}${pluginId}`;\n }\n\n // Database client overrides\n let databaseClientOverrides: Knex.Config = {};\n if (databaseName) {\n databaseClientOverrides = { connection: { database: databaseName } };\n }\n if (pluginDivisionMode === 'schema') {\n databaseClientOverrides = mergeDatabaseConfig({}, databaseClientOverrides, {\n searchPath: [pluginId],\n });\n }\n\n // Full knex config for plugin\n const knexConfig: Knex.Config = {\n ...additionalKnexConfig,\n client,\n connection,\n ...(role && { role }),\n };\n\n return {\n client,\n clientOverridden,\n role,\n additionalKnexConfig,\n ensureExists,\n ensureSchemaExists,\n pluginDivisionMode,\n connection,\n databaseName,\n databaseClientOverrides,\n knexConfig,\n };\n}\n\nexport class PgConnector implements Connector {\n private readonly config: Config;\n private readonly prefix: string;\n\n constructor(config: Config, prefix: string) {\n this.config = config;\n this.prefix = prefix;\n }\n\n async getClient(\n pluginId: string,\n _deps: {\n logger: LoggerService;\n lifecycle: LifecycleService;\n },\n ): Promise<Knex> {\n const pluginDbConfig = computePgPluginConfig(\n this.config,\n pluginId,\n this.prefix,\n );\n\n if (pluginDbConfig.databaseName && pluginDbConfig.ensureExists) {\n try {\n await ensurePgDatabaseExists(this.config, pluginDbConfig.databaseName);\n } catch (error) {\n throw new Error(\n `Failed to connect to the database to make sure that '${pluginDbConfig.databaseName}' exists, ${error}`,\n );\n }\n }\n\n if (pluginDbConfig.pluginDivisionMode === 'schema') {\n if (pluginDbConfig.ensureSchemaExists || pluginDbConfig.ensureExists) {\n try {\n await ensurePgSchemaExists(this.config, 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 client = createPgDatabaseClient(\n this.config,\n mergeDatabaseConfig(\n pluginDbConfig.knexConfig,\n pluginDbConfig.databaseClientOverrides,\n ),\n );\n\n return client;\n }\n}\n"],"names":["limiterFactory","knexFactory","format","config","mergeDatabaseConfig","ConfigReader","omit","durationToMilliseconds","readDurationFromConfig","ForwardedError","merge"],"mappings":"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"}
|
|
@@ -25,18 +25,6 @@ function isValidCronFormat(c) {
|
|
|
25
25
|
function isValidTrigger(t) {
|
|
26
26
|
return t === "manual";
|
|
27
27
|
}
|
|
28
|
-
v4.z.object({
|
|
29
|
-
version: v4.z.literal(1),
|
|
30
|
-
initialDelayDuration: v4.z.string().optional().refine(isValidOptionalDurationString, {
|
|
31
|
-
message: "Invalid duration, expecting ISO Period"
|
|
32
|
-
}),
|
|
33
|
-
recurringAtMostEveryDuration: v4.z.string().refine(isValidOptionalDurationString, {
|
|
34
|
-
message: "Invalid duration, expecting ISO Period"
|
|
35
|
-
}),
|
|
36
|
-
timeoutAfterDuration: v4.z.string().refine(isValidOptionalDurationString, {
|
|
37
|
-
message: "Invalid duration, expecting ISO Period"
|
|
38
|
-
})
|
|
39
|
-
});
|
|
40
28
|
const taskSettingsV2Schema = v4.z.object({
|
|
41
29
|
version: v4.z.literal(2),
|
|
42
30
|
cadence: v4.z.string().refine(isValidCronFormat, { message: "Invalid cron" }).or(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.cjs.js","sources":["../../../../src/entrypoints/scheduler/lib/types.ts"],"sourcesContent":["/*\n * Copyright 2021 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 { JsonObject } from '@backstage/types';\nimport { CronTime } from 'cron';\nimport { Duration } from 'luxon';\nimport { z } from 'zod/v4';\n\nfunction isValidOptionalDurationString(d: string | undefined): boolean {\n try {\n return !d || Duration.fromISO(d).isValid;\n } catch {\n return false;\n }\n}\n\nfunction isValidCronFormat(c: string | undefined): boolean {\n try {\n if (!c) {\n return false;\n }\n // parse cron format to ensure it's a valid format.\n // eslint-disable-next-line no-new\n new CronTime(c);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction isValidTrigger(t: string): boolean {\n return t === 'manual';\n}\n\nexport const
|
|
1
|
+
{"version":3,"file":"types.cjs.js","sources":["../../../../src/entrypoints/scheduler/lib/types.ts"],"sourcesContent":["/*\n * Copyright 2021 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 { JsonObject } from '@backstage/types';\nimport { CronTime } from 'cron';\nimport { Duration } from 'luxon';\nimport { z } from 'zod/v4';\n\nfunction isValidOptionalDurationString(d: string | undefined): boolean {\n try {\n return !d || Duration.fromISO(d).isValid;\n } catch {\n return false;\n }\n}\n\nfunction isValidCronFormat(c: string | undefined): boolean {\n try {\n if (!c) {\n return false;\n }\n // parse cron format to ensure it's a valid format.\n // eslint-disable-next-line no-new\n new CronTime(c);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction isValidTrigger(t: string): boolean {\n return t === 'manual';\n}\n\nexport const taskSettingsV2Schema = z.object({\n version: z.literal(2),\n cadence: z\n .string()\n .refine(isValidCronFormat, { message: 'Invalid cron' })\n .or(\n z.string().refine(isValidTrigger, {\n message: \"Invalid trigger, expecting 'manual'\",\n }),\n )\n .or(\n z.string().refine(isValidOptionalDurationString, {\n message: 'Invalid duration, expecting ISO Period',\n }),\n ),\n timeoutAfterDuration: z.string().refine(isValidOptionalDurationString, {\n message: 'Invalid duration, expecting ISO Period',\n }),\n initialDelayDuration: z\n .string()\n .optional()\n .refine(isValidOptionalDurationString, {\n message: 'Invalid duration, expecting ISO Period',\n }),\n});\n\n/**\n * The properties that control a scheduled task (version 2).\n */\nexport type TaskSettingsV2 = z.infer<typeof taskSettingsV2Schema>;\n\n/**\n * The shape of a task definition as returned by the service's REST API.\n */\nexport interface TaskApiTasksResponse {\n taskId: string;\n pluginId: string;\n scope: 'global' | 'local';\n settings: { version: number } & JsonObject;\n taskState:\n | {\n status: 'running';\n startedAt: string;\n timesOutAt?: string;\n lastRunError?: string;\n lastRunEndedAt?: string;\n }\n | {\n status: 'idle';\n startsAt?: string;\n lastRunError?: string;\n lastRunEndedAt?: string;\n }\n | null;\n workerState:\n | {\n status: 'initial-wait';\n }\n | {\n status: 'idle';\n }\n | {\n status: 'running';\n }\n | null;\n}\n"],"names":["Duration","CronTime","z"],"mappings":";;;;;;AAqBA,SAAS,8BAA8B,CAAA,EAAgC;AACrE,EAAA,IAAI;AACF,IAAA,OAAO,CAAC,CAAA,IAAKA,cAAA,CAAS,OAAA,CAAQ,CAAC,CAAA,CAAE,OAAA;AAAA,EACnC,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEA,SAAS,kBAAkB,CAAA,EAAgC;AACzD,EAAA,IAAI;AACF,IAAA,IAAI,CAAC,CAAA,EAAG;AACN,MAAA,OAAO,KAAA;AAAA,IACT;AAGA,IAAA,IAAIC,cAAS,CAAC,CAAA;AACd,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEA,SAAS,eAAe,CAAA,EAAoB;AAC1C,EAAA,OAAO,CAAA,KAAM,QAAA;AACf;AAEO,MAAM,oBAAA,GAAuBC,KAAE,MAAA,CAAO;AAAA,EAC3C,OAAA,EAASA,IAAA,CAAE,OAAA,CAAQ,CAAC,CAAA;AAAA,EACpB,OAAA,EAASA,IAAA,CACN,MAAA,EAAO,CACP,MAAA,CAAO,mBAAmB,EAAE,OAAA,EAAS,cAAA,EAAgB,CAAA,CACrD,EAAA;AAAA,IACCA,IAAA,CAAE,MAAA,EAAO,CAAE,MAAA,CAAO,cAAA,EAAgB;AAAA,MAChC,OAAA,EAAS;AAAA,KACV;AAAA,GACH,CACC,EAAA;AAAA,IACCA,IAAA,CAAE,MAAA,EAAO,CAAE,MAAA,CAAO,6BAAA,EAA+B;AAAA,MAC/C,OAAA,EAAS;AAAA,KACV;AAAA,GACH;AAAA,EACF,oBAAA,EAAsBA,IAAA,CAAE,MAAA,EAAO,CAAE,OAAO,6BAAA,EAA+B;AAAA,IACrE,OAAA,EAAS;AAAA,GACV,CAAA;AAAA,EACD,sBAAsBA,IAAA,CACnB,MAAA,GACA,QAAA,EAAS,CACT,OAAO,6BAAA,EAA+B;AAAA,IACrC,OAAA,EAAS;AAAA,GACV;AACL,CAAC;;;;"}
|
|
@@ -28,21 +28,35 @@ function nowPlus(duration, knex) {
|
|
|
28
28
|
}
|
|
29
29
|
return knex.raw(`now() + interval '${seconds} seconds'`);
|
|
30
30
|
}
|
|
31
|
+
const MAX_TIMEOUT_MS = 2 ** 30;
|
|
31
32
|
async function sleep(duration, abortSignal) {
|
|
32
33
|
if (abortSignal?.aborted) {
|
|
33
34
|
return;
|
|
34
35
|
}
|
|
36
|
+
let remaining = duration.as("milliseconds");
|
|
37
|
+
if (!Number.isFinite(remaining) || remaining <= 0) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
35
40
|
await new Promise((resolve) => {
|
|
36
|
-
let timeoutHandle
|
|
37
|
-
const
|
|
41
|
+
let timeoutHandle;
|
|
42
|
+
const finish = () => {
|
|
38
43
|
if (timeoutHandle) {
|
|
39
44
|
clearTimeout(timeoutHandle);
|
|
40
45
|
}
|
|
41
|
-
abortSignal?.removeEventListener("abort",
|
|
46
|
+
abortSignal?.removeEventListener("abort", finish);
|
|
42
47
|
resolve();
|
|
43
48
|
};
|
|
44
|
-
|
|
45
|
-
|
|
49
|
+
const tick = () => {
|
|
50
|
+
if (remaining <= 0) {
|
|
51
|
+
finish();
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const chunk = Math.min(remaining, MAX_TIMEOUT_MS);
|
|
55
|
+
remaining -= chunk;
|
|
56
|
+
timeoutHandle = setTimeout(tick, chunk);
|
|
57
|
+
};
|
|
58
|
+
abortSignal?.addEventListener("abort", finish);
|
|
59
|
+
tick();
|
|
46
60
|
});
|
|
47
61
|
}
|
|
48
62
|
function delegateAbortController(parent) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.cjs.js","sources":["../../../../src/entrypoints/scheduler/lib/util.ts"],"sourcesContent":["/*\n * Copyright 2021 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 InputError,\n serializeError as internalSerializeError,\n} from '@backstage/errors';\nimport { Knex } from 'knex';\nimport { DateTime, Duration } from 'luxon';\n\nexport const TRACER_ID = 'backstage-service-scheduler';\n\n// Keep the IDs compatible with e.g. Prometheus labels\nexport function validateId(id: string) {\n if (typeof id !== 'string' || !id.trim()) {\n throw new InputError(`${id} is not a valid ID, expected non-empty string`);\n }\n}\n\nexport function dbTime(t: Date | string): DateTime {\n if (typeof t === 'string') {\n return DateTime.fromSQL(t);\n }\n return DateTime.fromJSDate(t);\n}\n\nexport function nowPlus(duration: Duration | undefined, knex: Knex) {\n const seconds = duration?.as('seconds') ?? 0;\n if (!seconds) {\n return knex.fn.now();\n }\n\n if (knex.client.config.client.includes('sqlite3')) {\n return knex.raw(`datetime('now', ?)`, [`${seconds} seconds`]);\n }\n\n if (knex.client.config.client.includes('mysql')) {\n return knex.raw(`now() + interval ${seconds} second`);\n }\n\n return knex.raw(`now() + interval '${seconds} seconds'`);\n}\n\n/**\n * Sleep for the given duration, but return sooner if the abort signal\n * triggers.\n *\n * @param duration - The amount of time to sleep, at most\n * @param abortSignal - An optional abort signal that short circuits the wait\n */\nexport async function sleep(\n duration: Duration,\n abortSignal?: AbortSignal,\n): Promise<void> {\n if (abortSignal?.aborted) {\n return;\n }\n\n await new Promise<void>(resolve => {\n let timeoutHandle: NodeJS.Timeout | undefined
|
|
1
|
+
{"version":3,"file":"util.cjs.js","sources":["../../../../src/entrypoints/scheduler/lib/util.ts"],"sourcesContent":["/*\n * Copyright 2021 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 InputError,\n serializeError as internalSerializeError,\n} from '@backstage/errors';\nimport { Knex } from 'knex';\nimport { DateTime, Duration } from 'luxon';\n\nexport const TRACER_ID = 'backstage-service-scheduler';\n\n// Keep the IDs compatible with e.g. Prometheus labels\nexport function validateId(id: string) {\n if (typeof id !== 'string' || !id.trim()) {\n throw new InputError(`${id} is not a valid ID, expected non-empty string`);\n }\n}\n\nexport function dbTime(t: Date | string): DateTime {\n if (typeof t === 'string') {\n return DateTime.fromSQL(t);\n }\n return DateTime.fromJSDate(t);\n}\n\nexport function nowPlus(duration: Duration | undefined, knex: Knex) {\n const seconds = duration?.as('seconds') ?? 0;\n if (!seconds) {\n return knex.fn.now();\n }\n\n if (knex.client.config.client.includes('sqlite3')) {\n return knex.raw(`datetime('now', ?)`, [`${seconds} seconds`]);\n }\n\n if (knex.client.config.client.includes('mysql')) {\n return knex.raw(`now() + interval ${seconds} second`);\n }\n\n return knex.raw(`now() + interval '${seconds} seconds'`);\n}\n\n// Node.js setTimeout uses a 32-bit signed integer internally, so timeouts\n// longer than 2^31-1 ms (~24.8 days) fire immediately. We cap each individual\n// wait at 2^30 ms (~12.4 days) and loop until the full duration has elapsed.\nconst MAX_TIMEOUT_MS = 2 ** 30;\n\n/**\n * Sleep for the given duration, but return sooner if the abort signal\n * triggers.\n *\n * @param duration - The amount of time to sleep, at most\n * @param abortSignal - An optional abort signal that short circuits the wait\n */\nexport async function sleep(\n duration: Duration,\n abortSignal?: AbortSignal,\n): Promise<void> {\n if (abortSignal?.aborted) {\n return;\n }\n\n let remaining = duration.as('milliseconds');\n if (!Number.isFinite(remaining) || remaining <= 0) {\n return;\n }\n\n await new Promise<void>(resolve => {\n let timeoutHandle: NodeJS.Timeout | undefined;\n\n const finish = () => {\n if (timeoutHandle) {\n clearTimeout(timeoutHandle);\n }\n abortSignal?.removeEventListener('abort', finish);\n resolve();\n };\n\n const tick = () => {\n if (remaining <= 0) {\n finish();\n return;\n }\n const chunk = Math.min(remaining, MAX_TIMEOUT_MS);\n remaining -= chunk;\n timeoutHandle = setTimeout(tick, chunk);\n };\n\n abortSignal?.addEventListener('abort', finish);\n tick();\n });\n}\n\n/**\n * Creates a new AbortController that, in addition to working as a regular\n * standalone controller, also gets aborted if the given parent signal\n * reaches aborted state.\n *\n * @param parent - The \"parent\" signal that can trigger the delegate\n */\nexport function delegateAbortController(parent?: AbortSignal): AbortController {\n const delegate = new AbortController();\n\n if (parent) {\n if (parent.aborted) {\n delegate.abort();\n } else {\n const onParentAborted = () => {\n delegate.abort();\n };\n\n const onChildAborted = () => {\n parent.removeEventListener('abort', onParentAborted);\n };\n\n parent.addEventListener('abort', onParentAborted, { once: true });\n delegate.signal.addEventListener('abort', onChildAborted, { once: true });\n }\n }\n\n return delegate;\n}\n\nexport function serializeError(error: Error): string {\n return JSON.stringify(\n internalSerializeError(error, {\n includeStack: process.env.NODE_ENV === 'development',\n }),\n );\n}\n"],"names":["InputError","DateTime","internalSerializeError"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.cjs.js","sources":["../../../../src/entrypoints/urlReader/lib/util.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 { PassThrough, Readable } from 'node:stream';\nimport { ReadableStream as WebReadableStream } from 'node:stream/web';\n\nexport function parseLastModified(\n value: string | null | undefined,\n): Date | undefined {\n if (!value) {\n return undefined;\n }\n\n try {\n const result = new Date(value);\n result.toISOString(); // triggers exception if input was invalid\n return result;\n } catch {\n return undefined;\n }\n}\n\nexport function responseToReadable(response: Response): Readable {\n return response.body\n ? Readable.from(toWeb(response.body))\n : new PassThrough().end();\n}\n\n// The NodeJS ReadableStream is that fetch returns is super basic and not even\n// iterable. This function converts it to the smarter, iterable stream/web\n// variant instead.\
|
|
1
|
+
{"version":3,"file":"util.cjs.js","sources":["../../../../src/entrypoints/urlReader/lib/util.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 { PassThrough, Readable } from 'node:stream';\nimport { ReadableStream as WebReadableStream } from 'node:stream/web';\n\nexport function parseLastModified(\n value: string | null | undefined,\n): Date | undefined {\n if (!value) {\n return undefined;\n }\n\n try {\n const result = new Date(value);\n result.toISOString(); // triggers exception if input was invalid\n return result;\n } catch {\n return undefined;\n }\n}\n\nexport function responseToReadable(response: Response): Readable {\n return response.body\n ? Readable.from(toWeb(response.body))\n : new PassThrough().end();\n}\n\n// The NodeJS ReadableStream is that fetch returns is super basic and not even\n// iterable. This function converts it to the smarter, iterable stream/web\n// variant instead.\nfunction toWeb(\n responseBody: ReadableStream<Uint8Array>,\n): WebReadableStream<Uint8Array> {\n const reader = responseBody.getReader();\n return new WebReadableStream({\n async pull(controller) {\n const { value, done } = await reader.read();\n if (value) {\n controller.enqueue(value);\n }\n if (done) {\n controller.close();\n }\n },\n });\n}\n"],"names":["Readable","PassThrough","WebReadableStream"],"mappings":";;;;;AAmBO,SAAS,kBACd,KAAA,EACkB;AAClB,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,IAAI,IAAA,CAAK,KAAK,CAAA;AAC7B,IAAA,MAAA,CAAO,WAAA,EAAY;AACnB,IAAA,OAAO,MAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,MAAA;AAAA,EACT;AACF;AAEO,SAAS,mBAAmB,QAAA,EAA8B;AAC/D,EAAA,OAAO,QAAA,CAAS,IAAA,GACZA,oBAAA,CAAS,IAAA,CAAK,KAAA,CAAM,QAAA,CAAS,IAAI,CAAC,CAAA,GAClC,IAAIC,uBAAA,EAAY,CAAE,GAAA,EAAI;AAC5B;AAKA,SAAS,MACP,YAAA,EAC+B;AAC/B,EAAA,MAAM,MAAA,GAAS,aAAa,SAAA,EAAU;AACtC,EAAA,OAAO,IAAIC,kBAAA,CAAkB;AAAA,IAC3B,MAAM,KAAK,UAAA,EAAY;AACrB,MAAA,MAAM,EAAE,KAAA,EAAO,IAAA,EAAK,GAAI,MAAM,OAAO,IAAA,EAAK;AAC1C,MAAA,IAAI,KAAA,EAAO;AACT,QAAA,UAAA,CAAW,QAAQ,KAAK,CAAA;AAAA,MAC1B;AACA,MAAA,IAAI,IAAA,EAAM;AACR,QAAA,UAAA,CAAW,KAAA,EAAM;AAAA,MACnB;AAAA,IACF;AAAA,GACD,CAAA;AACH;;;;;"}
|
package/dist/index.cjs.js
CHANGED
|
@@ -6,5 +6,6 @@ var discoveryFeatureLoader = require('./discoveryFeatureLoader.cjs.js');
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
exports.createBackend = CreateBackend.createBackend;
|
|
9
|
+
exports.defaultServiceFactories = CreateBackend.defaultServiceFactories;
|
|
9
10
|
exports.discoveryFeatureLoader = discoveryFeatureLoader.discoveryFeatureLoader;
|
|
10
11
|
//# sourceMappingURL=index.cjs.js.map
|
package/dist/index.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { Backend } from '@backstage/backend-app-api';
|
|
2
2
|
import * as _backstage_backend_plugin_api from '@backstage/backend-plugin-api';
|
|
3
|
+
import { ServiceFactory } from '@backstage/backend-plugin-api';
|
|
3
4
|
|
|
5
|
+
/** @public */
|
|
6
|
+
declare const defaultServiceFactories: ServiceFactory[];
|
|
4
7
|
/**
|
|
5
8
|
* @public
|
|
6
9
|
*/
|
|
@@ -26,4 +29,4 @@ declare function createBackend(): Backend;
|
|
|
26
29
|
*/
|
|
27
30
|
declare const discoveryFeatureLoader: _backstage_backend_plugin_api.BackendFeature;
|
|
28
31
|
|
|
29
|
-
export { createBackend, discoveryFeatureLoader };
|
|
32
|
+
export { createBackend, defaultServiceFactories, discoveryFeatureLoader };
|
package/dist/package.json.cjs.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/backend-defaults",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.1-next.0",
|
|
4
4
|
"description": "Backend defaults used by Backstage backend apps",
|
|
5
5
|
"backstage": {
|
|
6
6
|
"role": "node-library"
|
|
@@ -214,22 +214,23 @@
|
|
|
214
214
|
"@aws-sdk/client-codecommit": "^3.350.0",
|
|
215
215
|
"@aws-sdk/client-s3": "^3.350.0",
|
|
216
216
|
"@aws-sdk/credential-providers": "^3.350.0",
|
|
217
|
+
"@aws-sdk/rds-signer": "^3.0.0",
|
|
217
218
|
"@aws-sdk/types": "^3.347.0",
|
|
218
219
|
"@azure/identity": "^4.0.0",
|
|
219
220
|
"@azure/storage-blob": "^12.5.0",
|
|
220
|
-
"@backstage/backend-app-api": "1.
|
|
221
|
+
"@backstage/backend-app-api": "1.7.0-next.0",
|
|
221
222
|
"@backstage/backend-dev-utils": "0.1.7",
|
|
222
|
-
"@backstage/backend-plugin-api": "1.9.
|
|
223
|
-
"@backstage/cli-node": "0.3.
|
|
224
|
-
"@backstage/config": "1.3.
|
|
225
|
-
"@backstage/config-loader": "1.10.
|
|
226
|
-
"@backstage/errors": "1.3.
|
|
227
|
-
"@backstage/integration": "2.0.
|
|
228
|
-
"@backstage/integration-aws-node": "0.1.
|
|
229
|
-
"@backstage/plugin-auth-node": "0.7.
|
|
230
|
-
"@backstage/plugin-events-node": "0.4.
|
|
231
|
-
"@backstage/plugin-permission-common": "0.9.
|
|
232
|
-
"@backstage/plugin-permission-node": "0.10.
|
|
223
|
+
"@backstage/backend-plugin-api": "1.9.1-next.0",
|
|
224
|
+
"@backstage/cli-node": "0.3.2-next.0",
|
|
225
|
+
"@backstage/config": "1.3.8-next.0",
|
|
226
|
+
"@backstage/config-loader": "1.10.11-next.0",
|
|
227
|
+
"@backstage/errors": "1.3.1-next.0",
|
|
228
|
+
"@backstage/integration": "2.0.2-next.0",
|
|
229
|
+
"@backstage/integration-aws-node": "0.1.22-next.0",
|
|
230
|
+
"@backstage/plugin-auth-node": "0.7.1-next.0",
|
|
231
|
+
"@backstage/plugin-events-node": "0.4.22-next.0",
|
|
232
|
+
"@backstage/plugin-permission-common": "0.9.9-next.0",
|
|
233
|
+
"@backstage/plugin-permission-node": "0.10.13-next.0",
|
|
233
234
|
"@backstage/types": "1.2.2",
|
|
234
235
|
"@google-cloud/storage": "^7.0.0",
|
|
235
236
|
"@keyv/memcache": "^2.0.1",
|
|
@@ -285,9 +286,8 @@
|
|
|
285
286
|
},
|
|
286
287
|
"devDependencies": {
|
|
287
288
|
"@aws-sdk/util-stream-node": "^3.350.0",
|
|
288
|
-
"@backstage/backend-
|
|
289
|
-
"@backstage/
|
|
290
|
-
"@backstage/cli": "0.36.1-next.2",
|
|
289
|
+
"@backstage/backend-test-utils": "1.11.3-next.0",
|
|
290
|
+
"@backstage/cli": "0.36.2-next.0",
|
|
291
291
|
"@google-cloud/cloud-sql-connector": "^1.4.0",
|
|
292
292
|
"@types/archiver": "^7.0.0",
|
|
293
293
|
"@types/base64-stream": "^1.0.2",
|