@backstage/backend-defaults 0.5.1-next.2 → 0.5.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 +53 -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/entrypoints/auth/helpers.cjs.js +32 -18
- package/dist/entrypoints/auth/helpers.cjs.js.map +1 -1
- package/dist/entrypoints/database/DatabaseManager.cjs.js +3 -0
- package/dist/entrypoints/database/DatabaseManager.cjs.js.map +1 -1
- package/dist/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.cjs.js +3 -0
- package/dist/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/lib/GitlabUrlReader.cjs.js +1 -2
- package/dist/entrypoints/urlReader/lib/GitlabUrlReader.cjs.js.map +1 -1
- package/dist/package.json.cjs.js +1 -1
- package/dist/urlReader.d.ts +1 -2
- 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 +18 -18
- 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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,58 @@
|
|
|
1
1
|
# @backstage/backend-defaults
|
|
2
2
|
|
|
3
|
+
## 0.5.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies
|
|
8
|
+
- @backstage/plugin-events-node@0.4.2
|
|
9
|
+
- @backstage/backend-app-api@1.0.1
|
|
10
|
+
- @backstage/backend-plugin-api@1.0.1
|
|
11
|
+
- @backstage/cli-node@0.2.9
|
|
12
|
+
- @backstage/config-loader@1.9.1
|
|
13
|
+
- @backstage/plugin-auth-node@0.5.3
|
|
14
|
+
- @backstage/plugin-permission-node@0.8.4
|
|
15
|
+
|
|
16
|
+
## 0.5.1
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- 4b60e0c: Small tweaks to API reports to make them valid
|
|
21
|
+
- 321a994: Sensitive internal fields on `BackstageCredentials` objects are now defined as read-only properties in order to minimize risk of leakage.
|
|
22
|
+
- ffd1f4a: Plugin lifecycle shutdown hooks are now performed before root lifecycle shutdown hooks.
|
|
23
|
+
- ffd1f4a: The database manager now attempts to close any database connections in a root lifecycle shutdown hook.
|
|
24
|
+
- e36d12f: The task scheduler now attempts to abort any tasks if it detects that Backstage is being shut down.
|
|
25
|
+
- fd6e6f4: build(deps): bump `cookie` from 0.6.0 to 0.7.0
|
|
26
|
+
- 094eaa3: Remove references to in-repo backend-common
|
|
27
|
+
- 720a2f9: Updated dependency `git-url-parse` to `^15.0.0`.
|
|
28
|
+
- 920004b: Updating error message for getProjectId when fetching Gitlab project from its url to be more accurate
|
|
29
|
+
- d7b44f0: Fix for backend shutdown hanging during local development due to SQLite connection shutdown never resolving.
|
|
30
|
+
- 8fd7deb: The default root HTTP service implementation will now pretty-print JSON responses in development.
|
|
31
|
+
|
|
32
|
+
If you are overriding the `rootHttpRouterServiceFactory` with a `configure` function that doesn't call `applyDefaults`, you can introduce this functionality by adding the following snippet inside `configure`:
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
if (process.env.NODE_ENV === 'development') {
|
|
36
|
+
app.set('json spaces', 2);
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
- Updated dependencies
|
|
41
|
+
- @backstage/cli-node@0.2.9
|
|
42
|
+
- @backstage/backend-app-api@1.0.1
|
|
43
|
+
- @backstage/plugin-auth-node@0.5.3
|
|
44
|
+
- @backstage/plugin-permission-node@0.8.4
|
|
45
|
+
- @backstage/plugin-events-node@0.4.1
|
|
46
|
+
- @backstage/integration@1.15.1
|
|
47
|
+
- @backstage/backend-dev-utils@0.1.5
|
|
48
|
+
- @backstage/backend-plugin-api@1.0.1
|
|
49
|
+
- @backstage/cli-common@0.1.14
|
|
50
|
+
- @backstage/config@1.2.0
|
|
51
|
+
- @backstage/config-loader@1.9.1
|
|
52
|
+
- @backstage/errors@1.2.4
|
|
53
|
+
- @backstage/integration-aws-node@0.1.12
|
|
54
|
+
- @backstage/types@1.1.1
|
|
55
|
+
|
|
3
56
|
## 0.5.1-next.2
|
|
4
57
|
|
|
5
58
|
### Patch Changes
|
package/auth/package.json
CHANGED
package/cache/package.json
CHANGED
package/database/package.json
CHANGED
package/discovery/package.json
CHANGED
|
@@ -1,28 +1,42 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
function createCredentialsWithServicePrincipal(sub, token, accessRestrictions) {
|
|
4
|
-
return
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
4
|
+
return Object.defineProperty(
|
|
5
|
+
{
|
|
6
|
+
$$type: "@backstage/BackstageCredentials",
|
|
7
|
+
version: "v1",
|
|
8
|
+
principal: {
|
|
9
|
+
type: "service",
|
|
10
|
+
subject: sub,
|
|
11
|
+
accessRestrictions
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"token",
|
|
15
|
+
{
|
|
16
|
+
enumerable: false,
|
|
17
|
+
configurable: true,
|
|
18
|
+
value: token
|
|
12
19
|
}
|
|
13
|
-
|
|
20
|
+
);
|
|
14
21
|
}
|
|
15
22
|
function createCredentialsWithUserPrincipal(sub, token, expiresAt) {
|
|
16
|
-
return
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
return Object.defineProperty(
|
|
24
|
+
{
|
|
25
|
+
$$type: "@backstage/BackstageCredentials",
|
|
26
|
+
version: "v1",
|
|
27
|
+
expiresAt,
|
|
28
|
+
principal: {
|
|
29
|
+
type: "user",
|
|
30
|
+
userEntityRef: sub
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"token",
|
|
34
|
+
{
|
|
35
|
+
enumerable: false,
|
|
36
|
+
configurable: true,
|
|
37
|
+
value: token
|
|
24
38
|
}
|
|
25
|
-
|
|
39
|
+
);
|
|
26
40
|
}
|
|
27
41
|
function createCredentialsWithNonePrincipal() {
|
|
28
42
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.cjs.js","sources":["../../../src/entrypoints/auth/helpers.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n BackstageCredentials,\n BackstageNonePrincipal,\n BackstagePrincipalAccessRestrictions,\n BackstageServicePrincipal,\n BackstageUserPrincipal,\n} from '@backstage/backend-plugin-api';\nimport { InternalBackstageCredentials } from './types';\n\nexport function createCredentialsWithServicePrincipal(\n sub: string,\n token?: string,\n accessRestrictions?: BackstagePrincipalAccessRestrictions,\n): InternalBackstageCredentials<BackstageServicePrincipal> {\n return {\n
|
|
1
|
+
{"version":3,"file":"helpers.cjs.js","sources":["../../../src/entrypoints/auth/helpers.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n BackstageCredentials,\n BackstageNonePrincipal,\n BackstagePrincipalAccessRestrictions,\n BackstageServicePrincipal,\n BackstageUserPrincipal,\n} from '@backstage/backend-plugin-api';\nimport { InternalBackstageCredentials } from './types';\n\nexport function createCredentialsWithServicePrincipal(\n sub: string,\n token?: string,\n accessRestrictions?: BackstagePrincipalAccessRestrictions,\n): InternalBackstageCredentials<BackstageServicePrincipal> {\n return Object.defineProperty(\n {\n $$type: '@backstage/BackstageCredentials',\n version: 'v1',\n principal: {\n type: 'service',\n subject: sub,\n accessRestrictions,\n },\n },\n 'token',\n {\n enumerable: false,\n configurable: true,\n value: token,\n },\n );\n}\n\nexport function createCredentialsWithUserPrincipal(\n sub: string,\n token: string,\n expiresAt?: Date,\n): InternalBackstageCredentials<BackstageUserPrincipal> {\n return Object.defineProperty(\n {\n $$type: '@backstage/BackstageCredentials',\n version: 'v1',\n expiresAt,\n principal: {\n type: 'user',\n userEntityRef: sub,\n },\n },\n 'token',\n {\n enumerable: false,\n configurable: true,\n value: token,\n },\n );\n}\n\nexport function createCredentialsWithNonePrincipal(): InternalBackstageCredentials<BackstageNonePrincipal> {\n return {\n $$type: '@backstage/BackstageCredentials',\n version: 'v1',\n principal: {\n type: 'none',\n },\n };\n}\n\nexport function toInternalBackstageCredentials(\n credentials: BackstageCredentials,\n): InternalBackstageCredentials<\n BackstageUserPrincipal | BackstageServicePrincipal | BackstageNonePrincipal\n> {\n if (credentials.$$type !== '@backstage/BackstageCredentials') {\n throw new Error('Invalid credential type');\n }\n\n const internalCredentials = credentials as InternalBackstageCredentials<\n BackstageUserPrincipal | BackstageServicePrincipal | BackstageNonePrincipal\n >;\n\n if (internalCredentials.version !== 'v1') {\n throw new Error(\n `Invalid credential version ${internalCredentials.version}`,\n );\n }\n\n return internalCredentials;\n}\n"],"names":[],"mappings":";;AAyBgB,SAAA,qCAAA,CACd,GACA,EAAA,KAAA,EACA,kBACyD,EAAA;AACzD,EAAA,OAAO,MAAO,CAAA,cAAA;AAAA,IACZ;AAAA,MACE,MAAQ,EAAA,iCAAA;AAAA,MACR,OAAS,EAAA,IAAA;AAAA,MACT,SAAW,EAAA;AAAA,QACT,IAAM,EAAA,SAAA;AAAA,QACN,OAAS,EAAA,GAAA;AAAA,QACT,kBAAA;AAAA,OACF;AAAA,KACF;AAAA,IACA,OAAA;AAAA,IACA;AAAA,MACE,UAAY,EAAA,KAAA;AAAA,MACZ,YAAc,EAAA,IAAA;AAAA,MACd,KAAO,EAAA,KAAA;AAAA,KACT;AAAA,GACF,CAAA;AACF,CAAA;AAEgB,SAAA,kCAAA,CACd,GACA,EAAA,KAAA,EACA,SACsD,EAAA;AACtD,EAAA,OAAO,MAAO,CAAA,cAAA;AAAA,IACZ;AAAA,MACE,MAAQ,EAAA,iCAAA;AAAA,MACR,OAAS,EAAA,IAAA;AAAA,MACT,SAAA;AAAA,MACA,SAAW,EAAA;AAAA,QACT,IAAM,EAAA,MAAA;AAAA,QACN,aAAe,EAAA,GAAA;AAAA,OACjB;AAAA,KACF;AAAA,IACA,OAAA;AAAA,IACA;AAAA,MACE,UAAY,EAAA,KAAA;AAAA,MACZ,YAAc,EAAA,IAAA;AAAA,MACd,KAAO,EAAA,KAAA;AAAA,KACT;AAAA,GACF,CAAA;AACF,CAAA;AAEO,SAAS,kCAA2F,GAAA;AACzG,EAAO,OAAA;AAAA,IACL,MAAQ,EAAA,iCAAA;AAAA,IACR,OAAS,EAAA,IAAA;AAAA,IACT,SAAW,EAAA;AAAA,MACT,IAAM,EAAA,MAAA;AAAA,KACR;AAAA,GACF,CAAA;AACF,CAAA;AAEO,SAAS,+BACd,WAGA,EAAA;AACA,EAAI,IAAA,WAAA,CAAY,WAAW,iCAAmC,EAAA;AAC5D,IAAM,MAAA,IAAI,MAAM,yBAAyB,CAAA,CAAA;AAAA,GAC3C;AAEA,EAAA,MAAM,mBAAsB,GAAA,WAAA,CAAA;AAI5B,EAAI,IAAA,mBAAA,CAAoB,YAAY,IAAM,EAAA;AACxC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,2BAAA,EAA8B,oBAAoB,OAAO,CAAA,CAAA;AAAA,KAC3D,CAAA;AAAA,GACF;AAEA,EAAO,OAAA,mBAAA,CAAA;AACT;;;;;;;"}
|
|
@@ -52,6 +52,9 @@ class DatabaseManagerImpl {
|
|
|
52
52
|
clearInterval(this.keepaliveIntervals.get(pluginId));
|
|
53
53
|
const connection = await this.databaseCache.get(pluginId);
|
|
54
54
|
if (connection) {
|
|
55
|
+
if (connection.client.config.includes("sqlite3")) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
55
58
|
await connection.destroy().catch((error) => {
|
|
56
59
|
deps?.logger?.error(
|
|
57
60
|
`Problem closing database connection for ${pluginId}: ${errors.stringifyError(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DatabaseManager.cjs.js","sources":["../../../src/entrypoints/database/DatabaseManager.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 DatabaseService,\n LifecycleService,\n LoggerService,\n RootConfigService,\n RootLifecycleService,\n RootLoggerService,\n} from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { stringifyError } from '@backstage/errors';\nimport { Knex } from 'knex';\nimport { MysqlConnector } from './connectors/mysql';\nimport { PgConnector } from './connectors/postgres';\nimport { Sqlite3Connector } from './connectors/sqlite3';\nimport { Connector, PluginDatabaseManager } from './types';\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\n/**\n * Creation options for {@link DatabaseManager}.\n *\n * @public\n */\nexport type DatabaseManagerOptions = {\n migrations?: DatabaseService['migrations'];\n rootLogger?: RootLoggerService;\n rootLifecycle?: RootLifecycleService;\n};\n\n/**\n * Testable implementation class for {@link DatabaseManager} below.\n */\nexport class DatabaseManagerImpl {\n constructor(\n private readonly config: Config,\n private readonly connectors: Record<string, Connector>,\n private readonly options?: DatabaseManagerOptions,\n private readonly databaseCache: Map<string, Promise<Knex>> = new Map(),\n private readonly keepaliveIntervals: Map<\n string,\n NodeJS.Timeout\n > = new Map(),\n ) {\n // If a rootLifecycle service was provided, register a shutdown hook to\n // clean up any database connections.\n if (options?.rootLifecycle !== undefined) {\n options.rootLifecycle.addShutdownHook(async () => {\n await this.shutdown({ logger: options.rootLogger });\n });\n }\n }\n\n /**\n * Generates a PluginDatabaseManager for consumption by plugins.\n *\n * @param pluginId - The plugin that the database manager should be created for. Plugin names\n * should be unique as they are used to look up database config overrides under\n * `backend.database.plugin`.\n */\n forPlugin(\n pluginId: string,\n deps: {\n logger: LoggerService;\n lifecycle: LifecycleService;\n },\n ): PluginDatabaseManager {\n const client = this.getClientType(pluginId).client;\n const connector = this.connectors[client];\n if (!connector) {\n throw new Error(\n `Unsupported database client type '${client}' specified for plugin '${pluginId}'`,\n );\n }\n const getClient = () => this.getDatabase(pluginId, connector, deps);\n\n const skip =\n this.options?.migrations?.skip ??\n this.config.getOptionalBoolean(\n `backend.database.plugin.${pluginId}.skipMigrations`,\n ) ??\n this.config.getOptionalBoolean('backend.database.skipMigrations') ??\n false;\n\n return { getClient, migrations: { skip } };\n }\n\n /**\n * Destroys all known connections.\n */\n private async shutdown(deps?: { logger?: LoggerService }): Promise<void> {\n const pluginIds = Array.from(this.databaseCache.keys());\n await Promise.allSettled(\n pluginIds.map(async pluginId => {\n // We no longer need to keep connections alive.\n clearInterval(this.keepaliveIntervals.get(pluginId));\n\n const connection = await this.databaseCache.get(pluginId);\n if (connection) {\n await connection.destroy().catch((error: unknown) => {\n deps?.logger?.error(\n `Problem closing database connection for ${pluginId}: ${stringifyError(\n error,\n )}`,\n );\n });\n }\n }),\n );\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 /**\n * Provides a scoped Knex client for a plugin as per application config.\n *\n * @param pluginId - Plugin to get a Knex client for\n * @returns Promise which resolves to a scoped Knex database client for a\n * plugin\n */\n private async getDatabase(\n pluginId: string,\n connector: Connector,\n deps: {\n logger: LoggerService;\n lifecycle: LifecycleService;\n },\n ): Promise<Knex> {\n if (this.databaseCache.has(pluginId)) {\n return this.databaseCache.get(pluginId)!;\n }\n\n const clientPromise = connector.getClient(pluginId, deps);\n this.databaseCache.set(pluginId, clientPromise);\n\n if (process.env.NODE_ENV !== 'test') {\n clientPromise.then(client =>\n this.startKeepaliveLoop(pluginId, client, deps.logger),\n );\n }\n\n return clientPromise;\n }\n\n private startKeepaliveLoop(\n pluginId: string,\n client: Knex,\n logger: LoggerService,\n ): void {\n let lastKeepaliveFailed = false;\n\n this.keepaliveIntervals.set(\n pluginId,\n setInterval(() => {\n // During testing it can happen that the environment is torn down and\n // this client is `undefined`, but this interval is still run.\n client?.raw('select 1').then(\n () => {\n lastKeepaliveFailed = false;\n },\n (error: unknown) => {\n if (!lastKeepaliveFailed) {\n lastKeepaliveFailed = true;\n logger.warn(\n `Database keepalive failed for plugin ${pluginId}, ${stringifyError(\n error,\n )}`,\n );\n }\n },\n );\n }, 60 * 1000),\n );\n }\n}\n\n// NOTE: This class looks odd but is kept around for API compatibility reasons\n/**\n * Manages database connections for Backstage backend plugins.\n *\n * @public\n * @remarks\n *\n * The database manager allows the user to set connection and client settings on\n * a per pluginId basis by defining a database config block under\n * `plugin.<pluginId>` in addition to top level defaults. Optionally, a user may\n * set `prefix` which is used to prefix generated database names if config is\n * not provided.\n */\nexport class DatabaseManager {\n /**\n * Creates a {@link DatabaseManager} from `backend.database` config.\n *\n * @param config - The loaded application configuration.\n * @param options - An optional configuration object.\n */\n static fromConfig(\n config: RootConfigService,\n options?: DatabaseManagerOptions,\n ): DatabaseManager {\n const databaseConfig = config.getConfig('backend.database');\n const prefix =\n databaseConfig.getOptionalString('prefix') || 'backstage_plugin_';\n return new DatabaseManager(\n new DatabaseManagerImpl(\n databaseConfig,\n {\n pg: new PgConnector(databaseConfig, prefix),\n sqlite3: new Sqlite3Connector(databaseConfig),\n 'better-sqlite3': new Sqlite3Connector(databaseConfig),\n mysql: new MysqlConnector(databaseConfig, prefix),\n mysql2: new MysqlConnector(databaseConfig, prefix),\n },\n options,\n ),\n );\n }\n\n private constructor(private readonly impl: DatabaseManagerImpl) {}\n\n /**\n * Generates a PluginDatabaseManager for consumption by plugins.\n *\n * @param pluginId - The plugin that the database manager should be created for. Plugin names\n * should be unique as they are used to look up database config overrides under\n * `backend.database.plugin`.\n */\n forPlugin(\n pluginId: string,\n deps: {\n logger: LoggerService;\n lifecycle: LifecycleService;\n },\n ): PluginDatabaseManager {\n return this.impl.forPlugin(pluginId, deps);\n }\n}\n"],"names":["stringifyError","PgConnector","Sqlite3Connector","MysqlConnector"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DatabaseManager.cjs.js","sources":["../../../src/entrypoints/database/DatabaseManager.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 DatabaseService,\n LifecycleService,\n LoggerService,\n RootConfigService,\n RootLifecycleService,\n RootLoggerService,\n} from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { stringifyError } from '@backstage/errors';\nimport { Knex } from 'knex';\nimport { MysqlConnector } from './connectors/mysql';\nimport { PgConnector } from './connectors/postgres';\nimport { Sqlite3Connector } from './connectors/sqlite3';\nimport { Connector, PluginDatabaseManager } from './types';\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\n/**\n * Creation options for {@link DatabaseManager}.\n *\n * @public\n */\nexport type DatabaseManagerOptions = {\n migrations?: DatabaseService['migrations'];\n rootLogger?: RootLoggerService;\n rootLifecycle?: RootLifecycleService;\n};\n\n/**\n * Testable implementation class for {@link DatabaseManager} below.\n */\nexport class DatabaseManagerImpl {\n constructor(\n private readonly config: Config,\n private readonly connectors: Record<string, Connector>,\n private readonly options?: DatabaseManagerOptions,\n private readonly databaseCache: Map<string, Promise<Knex>> = new Map(),\n private readonly keepaliveIntervals: Map<\n string,\n NodeJS.Timeout\n > = new Map(),\n ) {\n // If a rootLifecycle service was provided, register a shutdown hook to\n // clean up any database connections.\n if (options?.rootLifecycle !== undefined) {\n options.rootLifecycle.addShutdownHook(async () => {\n await this.shutdown({ logger: options.rootLogger });\n });\n }\n }\n\n /**\n * Generates a PluginDatabaseManager for consumption by plugins.\n *\n * @param pluginId - The plugin that the database manager should be created for. Plugin names\n * should be unique as they are used to look up database config overrides under\n * `backend.database.plugin`.\n */\n forPlugin(\n pluginId: string,\n deps: {\n logger: LoggerService;\n lifecycle: LifecycleService;\n },\n ): PluginDatabaseManager {\n const client = this.getClientType(pluginId).client;\n const connector = this.connectors[client];\n if (!connector) {\n throw new Error(\n `Unsupported database client type '${client}' specified for plugin '${pluginId}'`,\n );\n }\n const getClient = () => this.getDatabase(pluginId, connector, deps);\n\n const skip =\n this.options?.migrations?.skip ??\n this.config.getOptionalBoolean(\n `backend.database.plugin.${pluginId}.skipMigrations`,\n ) ??\n this.config.getOptionalBoolean('backend.database.skipMigrations') ??\n false;\n\n return { getClient, migrations: { skip } };\n }\n\n /**\n * Destroys all known connections.\n */\n private async shutdown(deps?: { logger?: LoggerService }): Promise<void> {\n const pluginIds = Array.from(this.databaseCache.keys());\n await Promise.allSettled(\n pluginIds.map(async pluginId => {\n // We no longer need to keep connections alive.\n clearInterval(this.keepaliveIntervals.get(pluginId));\n\n const connection = await this.databaseCache.get(pluginId);\n if (connection) {\n if (connection.client.config.includes('sqlite3')) {\n return; // sqlite3 does not support destroy, it hangs\n }\n await connection.destroy().catch((error: unknown) => {\n deps?.logger?.error(\n `Problem closing database connection for ${pluginId}: ${stringifyError(\n error,\n )}`,\n );\n });\n }\n }),\n );\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 /**\n * Provides a scoped Knex client for a plugin as per application config.\n *\n * @param pluginId - Plugin to get a Knex client for\n * @returns Promise which resolves to a scoped Knex database client for a\n * plugin\n */\n private async getDatabase(\n pluginId: string,\n connector: Connector,\n deps: {\n logger: LoggerService;\n lifecycle: LifecycleService;\n },\n ): Promise<Knex> {\n if (this.databaseCache.has(pluginId)) {\n return this.databaseCache.get(pluginId)!;\n }\n\n const clientPromise = connector.getClient(pluginId, deps);\n this.databaseCache.set(pluginId, clientPromise);\n\n if (process.env.NODE_ENV !== 'test') {\n clientPromise.then(client =>\n this.startKeepaliveLoop(pluginId, client, deps.logger),\n );\n }\n\n return clientPromise;\n }\n\n private startKeepaliveLoop(\n pluginId: string,\n client: Knex,\n logger: LoggerService,\n ): void {\n let lastKeepaliveFailed = false;\n\n this.keepaliveIntervals.set(\n pluginId,\n setInterval(() => {\n // During testing it can happen that the environment is torn down and\n // this client is `undefined`, but this interval is still run.\n client?.raw('select 1').then(\n () => {\n lastKeepaliveFailed = false;\n },\n (error: unknown) => {\n if (!lastKeepaliveFailed) {\n lastKeepaliveFailed = true;\n logger.warn(\n `Database keepalive failed for plugin ${pluginId}, ${stringifyError(\n error,\n )}`,\n );\n }\n },\n );\n }, 60 * 1000),\n );\n }\n}\n\n// NOTE: This class looks odd but is kept around for API compatibility reasons\n/**\n * Manages database connections for Backstage backend plugins.\n *\n * @public\n * @remarks\n *\n * The database manager allows the user to set connection and client settings on\n * a per pluginId basis by defining a database config block under\n * `plugin.<pluginId>` in addition to top level defaults. Optionally, a user may\n * set `prefix` which is used to prefix generated database names if config is\n * not provided.\n */\nexport class DatabaseManager {\n /**\n * Creates a {@link DatabaseManager} from `backend.database` config.\n *\n * @param config - The loaded application configuration.\n * @param options - An optional configuration object.\n */\n static fromConfig(\n config: RootConfigService,\n options?: DatabaseManagerOptions,\n ): DatabaseManager {\n const databaseConfig = config.getConfig('backend.database');\n const prefix =\n databaseConfig.getOptionalString('prefix') || 'backstage_plugin_';\n return new DatabaseManager(\n new DatabaseManagerImpl(\n databaseConfig,\n {\n pg: new PgConnector(databaseConfig, prefix),\n sqlite3: new Sqlite3Connector(databaseConfig),\n 'better-sqlite3': new Sqlite3Connector(databaseConfig),\n mysql: new MysqlConnector(databaseConfig, prefix),\n mysql2: new MysqlConnector(databaseConfig, prefix),\n },\n options,\n ),\n );\n }\n\n private constructor(private readonly impl: DatabaseManagerImpl) {}\n\n /**\n * Generates a PluginDatabaseManager for consumption by plugins.\n *\n * @param pluginId - The plugin that the database manager should be created for. Plugin names\n * should be unique as they are used to look up database config overrides under\n * `backend.database.plugin`.\n */\n forPlugin(\n pluginId: string,\n deps: {\n logger: LoggerService;\n lifecycle: LifecycleService;\n },\n ): PluginDatabaseManager {\n return this.impl.forPlugin(pluginId, deps);\n }\n}\n"],"names":["stringifyError","PgConnector","Sqlite3Connector","MysqlConnector"],"mappings":"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"}
|
|
@@ -49,6 +49,9 @@ const rootHttpRouterServiceFactoryWithOptions = (options) => backendPluginApi.cr
|
|
|
49
49
|
lifecycle,
|
|
50
50
|
healthRouter,
|
|
51
51
|
applyDefaults() {
|
|
52
|
+
if (process.env.NODE_ENV === "development") {
|
|
53
|
+
app.set("json spaces", 2);
|
|
54
|
+
}
|
|
52
55
|
app.use(middleware.helmet());
|
|
53
56
|
app.use(middleware.cors());
|
|
54
57
|
app.use(middleware.compression());
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rootHttpRouterServiceFactory.cjs.js","sources":["../../../src/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n RootConfigService,\n coreServices,\n createServiceFactory,\n LifecycleService,\n LoggerService,\n} from '@backstage/backend-plugin-api';\nimport express, { RequestHandler, Express } from 'express';\nimport type { Server } from 'node:http';\nimport {\n createHttpServer,\n MiddlewareFactory,\n readHttpServerOptions,\n} from './http';\nimport { DefaultRootHttpRouter } from './DefaultRootHttpRouter';\nimport { createHealthRouter } from './createHealthRouter';\n\n/**\n * @public\n */\nexport interface RootHttpRouterConfigureContext {\n app: Express;\n server: Server;\n middleware: MiddlewareFactory;\n routes: RequestHandler;\n config: RootConfigService;\n logger: LoggerService;\n lifecycle: LifecycleService;\n healthRouter: RequestHandler;\n applyDefaults: () => void;\n}\n\n/**\n * HTTP route registration for root services.\n *\n * See {@link @backstage/code-plugin-api#RootHttpRouterService}\n * and {@link https://backstage.io/docs/backend-system/core-services/root-http-router | the service docs}\n * for more information.\n *\n * @public\n */\nexport type RootHttpRouterFactoryOptions = {\n /**\n * The path to forward all unmatched requests to. Defaults to '/api/app' if\n * not given. Disables index path behavior if false is given.\n */\n indexPath?: string | false;\n\n configure?(context: RootHttpRouterConfigureContext): void;\n};\n\nfunction defaultConfigure({ applyDefaults }: RootHttpRouterConfigureContext) {\n applyDefaults();\n}\n\nconst rootHttpRouterServiceFactoryWithOptions = (\n options?: RootHttpRouterFactoryOptions,\n) =>\n createServiceFactory({\n service: coreServices.rootHttpRouter,\n deps: {\n config: coreServices.rootConfig,\n rootLogger: coreServices.rootLogger,\n lifecycle: coreServices.rootLifecycle,\n health: coreServices.rootHealth,\n },\n async factory({ config, rootLogger, lifecycle, health }) {\n const { indexPath, configure = defaultConfigure } = options ?? {};\n const logger = rootLogger.child({ service: 'rootHttpRouter' });\n const app = express();\n\n const router = DefaultRootHttpRouter.create({ indexPath });\n const middleware = MiddlewareFactory.create({ config, logger });\n const routes = router.handler();\n\n const healthRouter = createHealthRouter({ health });\n const server = await createHttpServer(\n app,\n readHttpServerOptions(config.getOptionalConfig('backend')),\n { logger },\n );\n\n configure({\n app,\n server,\n routes,\n middleware,\n config,\n logger,\n lifecycle,\n healthRouter,\n applyDefaults() {\n app.use(middleware.helmet());\n app.use(middleware.cors());\n app.use(middleware.compression());\n app.use(middleware.logging());\n app.use(healthRouter);\n app.use(routes);\n app.use(middleware.notFound());\n app.use(middleware.error());\n },\n });\n\n lifecycle.addShutdownHook(() => server.stop());\n\n await server.start();\n\n return router;\n },\n });\n\n/** @public */\nexport const rootHttpRouterServiceFactory = Object.assign(\n rootHttpRouterServiceFactoryWithOptions,\n rootHttpRouterServiceFactoryWithOptions(),\n);\n"],"names":["createServiceFactory","coreServices","config","express","DefaultRootHttpRouter","MiddlewareFactory","createHealthRouter","createHttpServer","readHttpServerOptions"],"mappings":";;;;;;;;;;;;;;;;;AAmEA,SAAS,gBAAA,CAAiB,EAAE,aAAA,EAAiD,EAAA;AAC3E,EAAc,aAAA,EAAA,CAAA;AAChB,CAAA;AAEA,MAAM,uCAAA,GAA0C,CAC9C,OAAA,KAEAA,qCAAqB,CAAA;AAAA,EACnB,SAASC,6BAAa,CAAA,cAAA;AAAA,EACtB,IAAM,EAAA;AAAA,IACJ,QAAQA,6BAAa,CAAA,UAAA;AAAA,IACrB,YAAYA,6BAAa,CAAA,UAAA;AAAA,IACzB,WAAWA,6BAAa,CAAA,aAAA;AAAA,IACxB,QAAQA,6BAAa,CAAA,UAAA;AAAA,GACvB;AAAA,EACA,MAAM,OAAQ,CAAA,UAAEC,UAAQ,UAAY,EAAA,SAAA,EAAW,QAAU,EAAA;AACvD,IAAA,MAAM,EAAE,SAAW,EAAA,SAAA,GAAY,gBAAiB,EAAA,GAAI,WAAW,EAAC,CAAA;AAChE,IAAA,MAAM,SAAS,UAAW,CAAA,KAAA,CAAM,EAAE,OAAA,EAAS,kBAAkB,CAAA,CAAA;AAC7D,IAAA,MAAM,MAAMC,wBAAQ,EAAA,CAAA;AAEpB,IAAA,MAAM,MAAS,GAAAC,2CAAA,CAAsB,MAAO,CAAA,EAAE,WAAW,CAAA,CAAA;AACzD,IAAA,MAAM,aAAaC,mCAAkB,CAAA,MAAA,CAAO,UAAEH,QAAA,EAAQ,QAAQ,CAAA,CAAA;AAC9D,IAAM,MAAA,MAAA,GAAS,OAAO,OAAQ,EAAA,CAAA;AAE9B,IAAA,MAAM,YAAe,GAAAI,qCAAA,CAAmB,EAAE,MAAA,EAAQ,CAAA,CAAA;AAClD,IAAA,MAAM,SAAS,MAAMC,iCAAA;AAAA,MACnB,GAAA;AAAA,MACAC,4BAAsB,CAAAN,QAAA,CAAO,iBAAkB,CAAA,SAAS,CAAC,CAAA;AAAA,MACzD,EAAE,MAAO,EAAA;AAAA,KACX,CAAA;AAEA,IAAU,SAAA,CAAA;AAAA,MACR,GAAA;AAAA,MACA,MAAA;AAAA,MACA,MAAA;AAAA,MACA,UAAA;AAAA,cACAA,QAAA;AAAA,MACA,MAAA;AAAA,MACA,SAAA;AAAA,MACA,YAAA;AAAA,MACA,aAAgB,GAAA;AACd,QAAI,GAAA,CAAA,GAAA,CAAI,UAAW,CAAA,MAAA,EAAQ,CAAA,CAAA;AAC3B,QAAI,GAAA,CAAA,GAAA,CAAI,UAAW,CAAA,IAAA,EAAM,CAAA,CAAA;AACzB,QAAI,GAAA,CAAA,GAAA,CAAI,UAAW,CAAA,WAAA,EAAa,CAAA,CAAA;AAChC,QAAI,GAAA,CAAA,GAAA,CAAI,UAAW,CAAA,OAAA,EAAS,CAAA,CAAA;AAC5B,QAAA,GAAA,CAAI,IAAI,YAAY,CAAA,CAAA;AACpB,QAAA,GAAA,CAAI,IAAI,MAAM,CAAA,CAAA;AACd,QAAI,GAAA,CAAA,GAAA,CAAI,UAAW,CAAA,QAAA,EAAU,CAAA,CAAA;AAC7B,QAAI,GAAA,CAAA,GAAA,CAAI,UAAW,CAAA,KAAA,EAAO,CAAA,CAAA;AAAA,OAC5B;AAAA,KACD,CAAA,CAAA;AAED,IAAA,SAAA,CAAU,eAAgB,CAAA,MAAM,MAAO,CAAA,IAAA,EAAM,CAAA,CAAA;AAE7C,IAAA,MAAM,OAAO,KAAM,EAAA,CAAA;AAEnB,IAAO,OAAA,MAAA,CAAA;AAAA,GACT;AACF,CAAC,CAAA,CAAA;AAGI,MAAM,+BAA+B,MAAO,CAAA,MAAA;AAAA,EACjD,uCAAA;AAAA,EACA,uCAAwC,EAAA;AAC1C;;;;"}
|
|
1
|
+
{"version":3,"file":"rootHttpRouterServiceFactory.cjs.js","sources":["../../../src/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n RootConfigService,\n coreServices,\n createServiceFactory,\n LifecycleService,\n LoggerService,\n} from '@backstage/backend-plugin-api';\nimport express, { RequestHandler, Express } from 'express';\nimport type { Server } from 'node:http';\nimport {\n createHttpServer,\n MiddlewareFactory,\n readHttpServerOptions,\n} from './http';\nimport { DefaultRootHttpRouter } from './DefaultRootHttpRouter';\nimport { createHealthRouter } from './createHealthRouter';\n\n/**\n * @public\n */\nexport interface RootHttpRouterConfigureContext {\n app: Express;\n server: Server;\n middleware: MiddlewareFactory;\n routes: RequestHandler;\n config: RootConfigService;\n logger: LoggerService;\n lifecycle: LifecycleService;\n healthRouter: RequestHandler;\n applyDefaults: () => void;\n}\n\n/**\n * HTTP route registration for root services.\n *\n * See {@link @backstage/code-plugin-api#RootHttpRouterService}\n * and {@link https://backstage.io/docs/backend-system/core-services/root-http-router | the service docs}\n * for more information.\n *\n * @public\n */\nexport type RootHttpRouterFactoryOptions = {\n /**\n * The path to forward all unmatched requests to. Defaults to '/api/app' if\n * not given. Disables index path behavior if false is given.\n */\n indexPath?: string | false;\n\n configure?(context: RootHttpRouterConfigureContext): void;\n};\n\nfunction defaultConfigure({ applyDefaults }: RootHttpRouterConfigureContext) {\n applyDefaults();\n}\n\nconst rootHttpRouterServiceFactoryWithOptions = (\n options?: RootHttpRouterFactoryOptions,\n) =>\n createServiceFactory({\n service: coreServices.rootHttpRouter,\n deps: {\n config: coreServices.rootConfig,\n rootLogger: coreServices.rootLogger,\n lifecycle: coreServices.rootLifecycle,\n health: coreServices.rootHealth,\n },\n async factory({ config, rootLogger, lifecycle, health }) {\n const { indexPath, configure = defaultConfigure } = options ?? {};\n const logger = rootLogger.child({ service: 'rootHttpRouter' });\n const app = express();\n\n const router = DefaultRootHttpRouter.create({ indexPath });\n const middleware = MiddlewareFactory.create({ config, logger });\n const routes = router.handler();\n\n const healthRouter = createHealthRouter({ health });\n const server = await createHttpServer(\n app,\n readHttpServerOptions(config.getOptionalConfig('backend')),\n { logger },\n );\n\n configure({\n app,\n server,\n routes,\n middleware,\n config,\n logger,\n lifecycle,\n healthRouter,\n applyDefaults() {\n if (process.env.NODE_ENV === 'development') {\n app.set('json spaces', 2);\n }\n app.use(middleware.helmet());\n app.use(middleware.cors());\n app.use(middleware.compression());\n app.use(middleware.logging());\n app.use(healthRouter);\n app.use(routes);\n app.use(middleware.notFound());\n app.use(middleware.error());\n },\n });\n\n lifecycle.addShutdownHook(() => server.stop());\n\n await server.start();\n\n return router;\n },\n });\n\n/** @public */\nexport const rootHttpRouterServiceFactory = Object.assign(\n rootHttpRouterServiceFactoryWithOptions,\n rootHttpRouterServiceFactoryWithOptions(),\n);\n"],"names":["createServiceFactory","coreServices","config","express","DefaultRootHttpRouter","MiddlewareFactory","createHealthRouter","createHttpServer","readHttpServerOptions"],"mappings":";;;;;;;;;;;;;;;;;AAmEA,SAAS,gBAAA,CAAiB,EAAE,aAAA,EAAiD,EAAA;AAC3E,EAAc,aAAA,EAAA,CAAA;AAChB,CAAA;AAEA,MAAM,uCAAA,GAA0C,CAC9C,OAAA,KAEAA,qCAAqB,CAAA;AAAA,EACnB,SAASC,6BAAa,CAAA,cAAA;AAAA,EACtB,IAAM,EAAA;AAAA,IACJ,QAAQA,6BAAa,CAAA,UAAA;AAAA,IACrB,YAAYA,6BAAa,CAAA,UAAA;AAAA,IACzB,WAAWA,6BAAa,CAAA,aAAA;AAAA,IACxB,QAAQA,6BAAa,CAAA,UAAA;AAAA,GACvB;AAAA,EACA,MAAM,OAAQ,CAAA,UAAEC,UAAQ,UAAY,EAAA,SAAA,EAAW,QAAU,EAAA;AACvD,IAAA,MAAM,EAAE,SAAW,EAAA,SAAA,GAAY,gBAAiB,EAAA,GAAI,WAAW,EAAC,CAAA;AAChE,IAAA,MAAM,SAAS,UAAW,CAAA,KAAA,CAAM,EAAE,OAAA,EAAS,kBAAkB,CAAA,CAAA;AAC7D,IAAA,MAAM,MAAMC,wBAAQ,EAAA,CAAA;AAEpB,IAAA,MAAM,MAAS,GAAAC,2CAAA,CAAsB,MAAO,CAAA,EAAE,WAAW,CAAA,CAAA;AACzD,IAAA,MAAM,aAAaC,mCAAkB,CAAA,MAAA,CAAO,UAAEH,QAAA,EAAQ,QAAQ,CAAA,CAAA;AAC9D,IAAM,MAAA,MAAA,GAAS,OAAO,OAAQ,EAAA,CAAA;AAE9B,IAAA,MAAM,YAAe,GAAAI,qCAAA,CAAmB,EAAE,MAAA,EAAQ,CAAA,CAAA;AAClD,IAAA,MAAM,SAAS,MAAMC,iCAAA;AAAA,MACnB,GAAA;AAAA,MACAC,4BAAsB,CAAAN,QAAA,CAAO,iBAAkB,CAAA,SAAS,CAAC,CAAA;AAAA,MACzD,EAAE,MAAO,EAAA;AAAA,KACX,CAAA;AAEA,IAAU,SAAA,CAAA;AAAA,MACR,GAAA;AAAA,MACA,MAAA;AAAA,MACA,MAAA;AAAA,MACA,UAAA;AAAA,cACAA,QAAA;AAAA,MACA,MAAA;AAAA,MACA,SAAA;AAAA,MACA,YAAA;AAAA,MACA,aAAgB,GAAA;AACd,QAAI,IAAA,OAAA,CAAQ,GAAI,CAAA,QAAA,KAAa,aAAe,EAAA;AAC1C,UAAI,GAAA,CAAA,GAAA,CAAI,eAAe,CAAC,CAAA,CAAA;AAAA,SAC1B;AACA,QAAI,GAAA,CAAA,GAAA,CAAI,UAAW,CAAA,MAAA,EAAQ,CAAA,CAAA;AAC3B,QAAI,GAAA,CAAA,GAAA,CAAI,UAAW,CAAA,IAAA,EAAM,CAAA,CAAA;AACzB,QAAI,GAAA,CAAA,GAAA,CAAI,UAAW,CAAA,WAAA,EAAa,CAAA,CAAA;AAChC,QAAI,GAAA,CAAA,GAAA,CAAI,UAAW,CAAA,OAAA,EAAS,CAAA,CAAA;AAC5B,QAAA,GAAA,CAAI,IAAI,YAAY,CAAA,CAAA;AACpB,QAAA,GAAA,CAAI,IAAI,MAAM,CAAA,CAAA;AACd,QAAI,GAAA,CAAA,GAAA,CAAI,UAAW,CAAA,QAAA,EAAU,CAAA,CAAA;AAC7B,QAAI,GAAA,CAAA,GAAA,CAAI,UAAW,CAAA,KAAA,EAAO,CAAA,CAAA;AAAA,OAC5B;AAAA,KACD,CAAA,CAAA;AAED,IAAA,SAAA,CAAU,eAAgB,CAAA,MAAM,MAAO,CAAA,IAAA,EAAM,CAAA,CAAA;AAE7C,IAAA,MAAM,OAAO,KAAM,EAAA,CAAA;AAEnB,IAAO,OAAA,MAAA,CAAA;AAAA,GACT;AACF,CAAC,CAAA,CAAA;AAGI,MAAM,+BAA+B,MAAO,CAAA,MAAA;AAAA,EACjD,uCAAA;AAAA,EACA,uCAAwC,EAAA;AAC1C;;;;"}
|
|
@@ -203,8 +203,7 @@ class GitlabUrlReader {
|
|
|
203
203
|
*
|
|
204
204
|
* E.g. `catalog/foo/*.yaml` will return `catalog/foo`.
|
|
205
205
|
*
|
|
206
|
-
* @param globPattern the glob pattern
|
|
207
|
-
* @private
|
|
206
|
+
* @param globPattern - the glob pattern
|
|
208
207
|
*/
|
|
209
208
|
getStaticPart(globPattern) {
|
|
210
209
|
const segments = globPattern.split("/");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GitlabUrlReader.cjs.js","sources":["../../../../src/entrypoints/urlReader/lib/GitlabUrlReader.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 {\n UrlReaderService,\n UrlReaderServiceReadTreeOptions,\n UrlReaderServiceReadTreeResponse,\n UrlReaderServiceReadUrlOptions,\n UrlReaderServiceReadUrlResponse,\n UrlReaderServiceSearchOptions,\n UrlReaderServiceSearchResponse,\n} from '@backstage/backend-plugin-api';\nimport { NotFoundError, NotModifiedError } from '@backstage/errors';\nimport {\n GitLabIntegration,\n ScmIntegrations,\n getGitLabFileFetchUrl,\n getGitLabIntegrationRelativePath,\n getGitLabRequestOptions,\n} from '@backstage/integration';\nimport parseGitUrl from 'git-url-parse';\nimport { trimEnd, trimStart } from 'lodash';\nimport { Minimatch } from 'minimatch';\nimport fetch, { Response } from 'node-fetch';\nimport { Readable } from 'stream';\nimport { ReadUrlResponseFactory } from './ReadUrlResponseFactory';\nimport { ReadTreeResponseFactory, ReaderFactory } from './types';\nimport { parseLastModified } from './util';\n\n/**\n * Implements a {@link @backstage/backend-plugin-api#UrlReaderService} for files on GitLab.\n *\n * @public\n */\nexport class GitlabUrlReader implements UrlReaderService {\n static factory: ReaderFactory = ({ config, treeResponseFactory }) => {\n const integrations = ScmIntegrations.fromConfig(config);\n return integrations.gitlab.list().map(integration => {\n const reader = new GitlabUrlReader(integration, {\n treeResponseFactory,\n });\n const predicate = (url: URL) => url.host === integration.config.host;\n return { reader, predicate };\n });\n };\n\n constructor(\n private readonly integration: GitLabIntegration,\n private readonly deps: { treeResponseFactory: ReadTreeResponseFactory },\n ) {}\n\n async read(url: string): Promise<Buffer> {\n const response = await this.readUrl(url);\n return response.buffer();\n }\n\n async readUrl(\n url: string,\n options?: UrlReaderServiceReadUrlOptions,\n ): Promise<UrlReaderServiceReadUrlResponse> {\n const { etag, lastModifiedAfter, signal, token } = options ?? {};\n const builtUrl = await this.getGitlabFetchUrl(url);\n\n let response: Response;\n try {\n response = await fetch(builtUrl, {\n headers: {\n ...getGitLabRequestOptions(this.integration.config, token).headers,\n ...(etag && { 'If-None-Match': etag }),\n ...(lastModifiedAfter && {\n 'If-Modified-Since': lastModifiedAfter.toUTCString(),\n }),\n },\n // TODO(freben): The signal cast is there because pre-3.x versions of\n // node-fetch have a very slightly deviating AbortSignal type signature.\n // The difference does not affect us in practice however. The cast can be\n // removed after we support ESM for CLI dependencies and migrate to\n // version 3 of node-fetch.\n // https://github.com/backstage/backstage/issues/8242\n ...(signal && { signal: signal as any }),\n });\n } catch (e) {\n throw new Error(`Unable to read ${url}, ${e}`);\n }\n\n if (response.status === 304) {\n throw new NotModifiedError();\n }\n\n if (response.ok) {\n return ReadUrlResponseFactory.fromNodeJSReadable(response.body, {\n etag: response.headers.get('ETag') ?? undefined,\n lastModifiedAt: parseLastModified(\n response.headers.get('Last-Modified'),\n ),\n });\n }\n\n const message = `${url} could not be read as ${builtUrl}, ${response.status} ${response.statusText}`;\n if (response.status === 404) {\n throw new NotFoundError(message);\n }\n throw new Error(message);\n }\n\n async readTree(\n url: string,\n options?: UrlReaderServiceReadTreeOptions,\n ): Promise<UrlReaderServiceReadTreeResponse> {\n const { etag, signal, token } = options ?? {};\n const { ref, full_name, filepath } = parseGitUrl(url);\n\n let repoFullName = full_name;\n\n const relativePath = getGitLabIntegrationRelativePath(\n this.integration.config,\n );\n\n // Considering self hosted gitlab with relative\n // assuming '/gitlab' is the relative path\n // from: /gitlab/repo/project\n // to: repo/project\n if (relativePath) {\n const rectifiedRelativePath = `${trimStart(relativePath, '/')}/`;\n repoFullName = full_name.replace(rectifiedRelativePath, '');\n }\n\n // Use GitLab API to get the default branch\n // encodeURIComponent is required for GitLab API\n // https://docs.gitlab.com/ee/api/README.html#namespaced-path-encoding\n const projectGitlabResponse = await fetch(\n new URL(\n `${this.integration.config.apiBaseUrl}/projects/${encodeURIComponent(\n repoFullName,\n )}`,\n ).toString(),\n getGitLabRequestOptions(this.integration.config, token),\n );\n if (!projectGitlabResponse.ok) {\n const msg = `Failed to read tree from ${url}, ${projectGitlabResponse.status} ${projectGitlabResponse.statusText}`;\n if (projectGitlabResponse.status === 404) {\n throw new NotFoundError(msg);\n }\n throw new Error(msg);\n }\n const projectGitlabResponseJson = await projectGitlabResponse.json();\n\n // ref is an empty string if no branch is set in provided url to readTree.\n const branch = ref || projectGitlabResponseJson.default_branch;\n\n // Fetch the latest commit that modifies the filepath in the provided or default branch\n // to compare against the provided sha.\n const commitsReqParams = new URLSearchParams();\n commitsReqParams.set('ref_name', branch);\n if (!!filepath) {\n commitsReqParams.set('path', filepath);\n }\n const commitsGitlabResponse = await fetch(\n new URL(\n `${this.integration.config.apiBaseUrl}/projects/${encodeURIComponent(\n repoFullName,\n )}/repository/commits?${commitsReqParams.toString()}`,\n ).toString(),\n {\n ...getGitLabRequestOptions(this.integration.config, token),\n // TODO(freben): The signal cast is there because pre-3.x versions of\n // node-fetch have a very slightly deviating AbortSignal type signature.\n // The difference does not affect us in practice however. The cast can\n // be removed after we support ESM for CLI dependencies and migrate to\n // version 3 of node-fetch.\n // https://github.com/backstage/backstage/issues/8242\n ...(signal && { signal: signal as any }),\n },\n );\n if (!commitsGitlabResponse.ok) {\n const message = `Failed to read tree (branch) from ${url}, ${commitsGitlabResponse.status} ${commitsGitlabResponse.statusText}`;\n if (commitsGitlabResponse.status === 404) {\n throw new NotFoundError(message);\n }\n throw new Error(message);\n }\n\n const commitSha = (await commitsGitlabResponse.json())[0]?.id ?? '';\n if (etag && etag === commitSha) {\n throw new NotModifiedError();\n }\n\n const archiveReqParams = new URLSearchParams();\n archiveReqParams.set('sha', branch);\n if (!!filepath) {\n archiveReqParams.set('path', filepath);\n }\n // https://docs.gitlab.com/ee/api/repositories.html#get-file-archive\n const archiveGitLabResponse = await fetch(\n `${this.integration.config.apiBaseUrl}/projects/${encodeURIComponent(\n repoFullName,\n )}/repository/archive?${archiveReqParams.toString()}`,\n {\n ...getGitLabRequestOptions(this.integration.config, token),\n // TODO(freben): The signal cast is there because pre-3.x versions of\n // node-fetch have a very slightly deviating AbortSignal type signature.\n // The difference does not affect us in practice however. The cast can\n // be removed after we support ESM for CLI dependencies and migrate to\n // version 3 of node-fetch.\n // https://github.com/backstage/backstage/issues/8242\n ...(signal && { signal: signal as any }),\n },\n );\n if (!archiveGitLabResponse.ok) {\n const message = `Failed to read tree (archive) from ${url}, ${archiveGitLabResponse.status} ${archiveGitLabResponse.statusText}`;\n if (archiveGitLabResponse.status === 404) {\n throw new NotFoundError(message);\n }\n throw new Error(message);\n }\n\n return await this.deps.treeResponseFactory.fromTarArchive({\n stream: Readable.from(archiveGitLabResponse.body),\n subpath: filepath,\n etag: commitSha,\n filter: options?.filter,\n });\n }\n\n async search(\n url: string,\n options?: UrlReaderServiceSearchOptions,\n ): Promise<UrlReaderServiceSearchResponse> {\n const { filepath } = parseGitUrl(url);\n const staticPart = this.getStaticPart(filepath);\n const matcher = new Minimatch(filepath);\n const treeUrl = trimEnd(url.replace(filepath, staticPart), `/`);\n const pathPrefix = staticPart ? `${staticPart}/` : '';\n const tree = await this.readTree(treeUrl, {\n etag: options?.etag,\n signal: options?.signal,\n filter: path => matcher.match(`${pathPrefix}${path}`),\n });\n\n const files = await tree.files();\n return {\n etag: tree.etag,\n files: files.map(file => ({\n url: this.integration.resolveUrl({\n url: `/${pathPrefix}${file.path}`,\n base: url,\n }),\n content: file.content,\n lastModifiedAt: file.lastModifiedAt,\n })),\n };\n }\n\n /**\n * This function splits the input globPattern string into segments using the path separator /. It then iterates over\n * the segments from the end of the array towards the beginning, checking if the concatenated string up to that\n * segment matches the original globPattern using the minimatch function. If a match is found, it continues iterating.\n * If no match is found, it returns the concatenated string up to the current segment, which is the static part of the\n * glob pattern.\n *\n * E.g. `catalog/foo/*.yaml` will return `catalog/foo`.\n *\n * @param globPattern the glob pattern\n * @private\n */\n private getStaticPart(globPattern: string) {\n const segments = globPattern.split('/');\n let i = segments.length;\n while (\n i > 0 &&\n new Minimatch(segments.slice(0, i).join('/')).match(globPattern)\n ) {\n i--;\n }\n return segments.slice(0, i).join('/');\n }\n\n toString() {\n const { host, token } = this.integration.config;\n return `gitlab{host=${host},authed=${Boolean(token)}}`;\n }\n\n private async getGitlabFetchUrl(target: string): Promise<string> {\n // If the target is for a job artifact then go down that path\n const targetUrl = new URL(target);\n if (targetUrl.pathname.includes('/-/jobs/artifacts/')) {\n return this.getGitlabArtifactFetchUrl(targetUrl).then(value =>\n value.toString(),\n );\n }\n // Default to the old behavior of assuming the url is for a file\n return getGitLabFileFetchUrl(target, this.integration.config);\n }\n\n // convert urls of the form:\n // https://example.com/<namespace>/<project>/-/jobs/artifacts/<ref>/raw/<path_to_file>?job=<job_name>\n // to urls of the form:\n // https://example.com/api/v4/projects/:id/jobs/artifacts/:ref_name/raw/*artifact_path?job=<job_name>\n private async getGitlabArtifactFetchUrl(target: URL): Promise<URL> {\n if (!target.pathname.includes('/-/jobs/artifacts/')) {\n throw new Error('Unable to process url as an GitLab artifact');\n }\n try {\n const [namespaceAndProject, ref] =\n target.pathname.split('/-/jobs/artifacts/');\n const projectPath = new URL(target);\n projectPath.pathname = namespaceAndProject;\n const projectId = await this.resolveProjectToId(projectPath);\n const relativePath = getGitLabIntegrationRelativePath(\n this.integration.config,\n );\n const newUrl = new URL(target);\n newUrl.pathname = `${relativePath}/api/v4/projects/${projectId}/jobs/artifacts/${ref}`;\n return newUrl;\n } catch (e) {\n throw new Error(\n `Unable to translate GitLab artifact URL: ${target}, ${e}`,\n );\n }\n }\n\n private async resolveProjectToId(pathToProject: URL): Promise<number> {\n let project = pathToProject.pathname;\n // Check relative path exist and remove it if so\n const relativePath = getGitLabIntegrationRelativePath(\n this.integration.config,\n );\n if (relativePath) {\n project = project.replace(relativePath, '');\n }\n // Trim an initial / if it exists\n project = project.replace(/^\\//, '');\n const result = await fetch(\n `${\n pathToProject.origin\n }${relativePath}/api/v4/projects/${encodeURIComponent(project)}`,\n getGitLabRequestOptions(this.integration.config),\n );\n const data = await result.json();\n if (!result.ok) {\n throw new Error(`Gitlab error: ${data.error}, ${data.error_description}`);\n }\n return Number(data.id);\n }\n}\n"],"names":["ScmIntegrations","fetch","getGitLabRequestOptions","NotModifiedError","ReadUrlResponseFactory","parseLastModified","NotFoundError","parseGitUrl","getGitLabIntegrationRelativePath","trimStart","Readable","Minimatch","trimEnd","getGitLabFileFetchUrl"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"GitlabUrlReader.cjs.js","sources":["../../../../src/entrypoints/urlReader/lib/GitlabUrlReader.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 {\n UrlReaderService,\n UrlReaderServiceReadTreeOptions,\n UrlReaderServiceReadTreeResponse,\n UrlReaderServiceReadUrlOptions,\n UrlReaderServiceReadUrlResponse,\n UrlReaderServiceSearchOptions,\n UrlReaderServiceSearchResponse,\n} from '@backstage/backend-plugin-api';\nimport { NotFoundError, NotModifiedError } from '@backstage/errors';\nimport {\n GitLabIntegration,\n ScmIntegrations,\n getGitLabFileFetchUrl,\n getGitLabIntegrationRelativePath,\n getGitLabRequestOptions,\n} from '@backstage/integration';\nimport parseGitUrl from 'git-url-parse';\nimport { trimEnd, trimStart } from 'lodash';\nimport { Minimatch } from 'minimatch';\nimport fetch, { Response } from 'node-fetch';\nimport { Readable } from 'stream';\nimport { ReadUrlResponseFactory } from './ReadUrlResponseFactory';\nimport { ReadTreeResponseFactory, ReaderFactory } from './types';\nimport { parseLastModified } from './util';\n\n/**\n * Implements a {@link @backstage/backend-plugin-api#UrlReaderService} for files on GitLab.\n *\n * @public\n */\nexport class GitlabUrlReader implements UrlReaderService {\n static factory: ReaderFactory = ({ config, treeResponseFactory }) => {\n const integrations = ScmIntegrations.fromConfig(config);\n return integrations.gitlab.list().map(integration => {\n const reader = new GitlabUrlReader(integration, {\n treeResponseFactory,\n });\n const predicate = (url: URL) => url.host === integration.config.host;\n return { reader, predicate };\n });\n };\n\n constructor(\n private readonly integration: GitLabIntegration,\n private readonly deps: { treeResponseFactory: ReadTreeResponseFactory },\n ) {}\n\n async read(url: string): Promise<Buffer> {\n const response = await this.readUrl(url);\n return response.buffer();\n }\n\n async readUrl(\n url: string,\n options?: UrlReaderServiceReadUrlOptions,\n ): Promise<UrlReaderServiceReadUrlResponse> {\n const { etag, lastModifiedAfter, signal, token } = options ?? {};\n const builtUrl = await this.getGitlabFetchUrl(url);\n\n let response: Response;\n try {\n response = await fetch(builtUrl, {\n headers: {\n ...getGitLabRequestOptions(this.integration.config, token).headers,\n ...(etag && { 'If-None-Match': etag }),\n ...(lastModifiedAfter && {\n 'If-Modified-Since': lastModifiedAfter.toUTCString(),\n }),\n },\n // TODO(freben): The signal cast is there because pre-3.x versions of\n // node-fetch have a very slightly deviating AbortSignal type signature.\n // The difference does not affect us in practice however. The cast can be\n // removed after we support ESM for CLI dependencies and migrate to\n // version 3 of node-fetch.\n // https://github.com/backstage/backstage/issues/8242\n ...(signal && { signal: signal as any }),\n });\n } catch (e) {\n throw new Error(`Unable to read ${url}, ${e}`);\n }\n\n if (response.status === 304) {\n throw new NotModifiedError();\n }\n\n if (response.ok) {\n return ReadUrlResponseFactory.fromNodeJSReadable(response.body, {\n etag: response.headers.get('ETag') ?? undefined,\n lastModifiedAt: parseLastModified(\n response.headers.get('Last-Modified'),\n ),\n });\n }\n\n const message = `${url} could not be read as ${builtUrl}, ${response.status} ${response.statusText}`;\n if (response.status === 404) {\n throw new NotFoundError(message);\n }\n throw new Error(message);\n }\n\n async readTree(\n url: string,\n options?: UrlReaderServiceReadTreeOptions,\n ): Promise<UrlReaderServiceReadTreeResponse> {\n const { etag, signal, token } = options ?? {};\n const { ref, full_name, filepath } = parseGitUrl(url);\n\n let repoFullName = full_name;\n\n const relativePath = getGitLabIntegrationRelativePath(\n this.integration.config,\n );\n\n // Considering self hosted gitlab with relative\n // assuming '/gitlab' is the relative path\n // from: /gitlab/repo/project\n // to: repo/project\n if (relativePath) {\n const rectifiedRelativePath = `${trimStart(relativePath, '/')}/`;\n repoFullName = full_name.replace(rectifiedRelativePath, '');\n }\n\n // Use GitLab API to get the default branch\n // encodeURIComponent is required for GitLab API\n // https://docs.gitlab.com/ee/api/README.html#namespaced-path-encoding\n const projectGitlabResponse = await fetch(\n new URL(\n `${this.integration.config.apiBaseUrl}/projects/${encodeURIComponent(\n repoFullName,\n )}`,\n ).toString(),\n getGitLabRequestOptions(this.integration.config, token),\n );\n if (!projectGitlabResponse.ok) {\n const msg = `Failed to read tree from ${url}, ${projectGitlabResponse.status} ${projectGitlabResponse.statusText}`;\n if (projectGitlabResponse.status === 404) {\n throw new NotFoundError(msg);\n }\n throw new Error(msg);\n }\n const projectGitlabResponseJson = await projectGitlabResponse.json();\n\n // ref is an empty string if no branch is set in provided url to readTree.\n const branch = ref || projectGitlabResponseJson.default_branch;\n\n // Fetch the latest commit that modifies the filepath in the provided or default branch\n // to compare against the provided sha.\n const commitsReqParams = new URLSearchParams();\n commitsReqParams.set('ref_name', branch);\n if (!!filepath) {\n commitsReqParams.set('path', filepath);\n }\n const commitsGitlabResponse = await fetch(\n new URL(\n `${this.integration.config.apiBaseUrl}/projects/${encodeURIComponent(\n repoFullName,\n )}/repository/commits?${commitsReqParams.toString()}`,\n ).toString(),\n {\n ...getGitLabRequestOptions(this.integration.config, token),\n // TODO(freben): The signal cast is there because pre-3.x versions of\n // node-fetch have a very slightly deviating AbortSignal type signature.\n // The difference does not affect us in practice however. The cast can\n // be removed after we support ESM for CLI dependencies and migrate to\n // version 3 of node-fetch.\n // https://github.com/backstage/backstage/issues/8242\n ...(signal && { signal: signal as any }),\n },\n );\n if (!commitsGitlabResponse.ok) {\n const message = `Failed to read tree (branch) from ${url}, ${commitsGitlabResponse.status} ${commitsGitlabResponse.statusText}`;\n if (commitsGitlabResponse.status === 404) {\n throw new NotFoundError(message);\n }\n throw new Error(message);\n }\n\n const commitSha = (await commitsGitlabResponse.json())[0]?.id ?? '';\n if (etag && etag === commitSha) {\n throw new NotModifiedError();\n }\n\n const archiveReqParams = new URLSearchParams();\n archiveReqParams.set('sha', branch);\n if (!!filepath) {\n archiveReqParams.set('path', filepath);\n }\n // https://docs.gitlab.com/ee/api/repositories.html#get-file-archive\n const archiveGitLabResponse = await fetch(\n `${this.integration.config.apiBaseUrl}/projects/${encodeURIComponent(\n repoFullName,\n )}/repository/archive?${archiveReqParams.toString()}`,\n {\n ...getGitLabRequestOptions(this.integration.config, token),\n // TODO(freben): The signal cast is there because pre-3.x versions of\n // node-fetch have a very slightly deviating AbortSignal type signature.\n // The difference does not affect us in practice however. The cast can\n // be removed after we support ESM for CLI dependencies and migrate to\n // version 3 of node-fetch.\n // https://github.com/backstage/backstage/issues/8242\n ...(signal && { signal: signal as any }),\n },\n );\n if (!archiveGitLabResponse.ok) {\n const message = `Failed to read tree (archive) from ${url}, ${archiveGitLabResponse.status} ${archiveGitLabResponse.statusText}`;\n if (archiveGitLabResponse.status === 404) {\n throw new NotFoundError(message);\n }\n throw new Error(message);\n }\n\n return await this.deps.treeResponseFactory.fromTarArchive({\n stream: Readable.from(archiveGitLabResponse.body),\n subpath: filepath,\n etag: commitSha,\n filter: options?.filter,\n });\n }\n\n async search(\n url: string,\n options?: UrlReaderServiceSearchOptions,\n ): Promise<UrlReaderServiceSearchResponse> {\n const { filepath } = parseGitUrl(url);\n const staticPart = this.getStaticPart(filepath);\n const matcher = new Minimatch(filepath);\n const treeUrl = trimEnd(url.replace(filepath, staticPart), `/`);\n const pathPrefix = staticPart ? `${staticPart}/` : '';\n const tree = await this.readTree(treeUrl, {\n etag: options?.etag,\n signal: options?.signal,\n filter: path => matcher.match(`${pathPrefix}${path}`),\n });\n\n const files = await tree.files();\n return {\n etag: tree.etag,\n files: files.map(file => ({\n url: this.integration.resolveUrl({\n url: `/${pathPrefix}${file.path}`,\n base: url,\n }),\n content: file.content,\n lastModifiedAt: file.lastModifiedAt,\n })),\n };\n }\n\n /**\n * This function splits the input globPattern string into segments using the path separator /. It then iterates over\n * the segments from the end of the array towards the beginning, checking if the concatenated string up to that\n * segment matches the original globPattern using the minimatch function. If a match is found, it continues iterating.\n * If no match is found, it returns the concatenated string up to the current segment, which is the static part of the\n * glob pattern.\n *\n * E.g. `catalog/foo/*.yaml` will return `catalog/foo`.\n *\n * @param globPattern - the glob pattern\n */\n private getStaticPart(globPattern: string) {\n const segments = globPattern.split('/');\n let i = segments.length;\n while (\n i > 0 &&\n new Minimatch(segments.slice(0, i).join('/')).match(globPattern)\n ) {\n i--;\n }\n return segments.slice(0, i).join('/');\n }\n\n toString() {\n const { host, token } = this.integration.config;\n return `gitlab{host=${host},authed=${Boolean(token)}}`;\n }\n\n private async getGitlabFetchUrl(target: string): Promise<string> {\n // If the target is for a job artifact then go down that path\n const targetUrl = new URL(target);\n if (targetUrl.pathname.includes('/-/jobs/artifacts/')) {\n return this.getGitlabArtifactFetchUrl(targetUrl).then(value =>\n value.toString(),\n );\n }\n // Default to the old behavior of assuming the url is for a file\n return getGitLabFileFetchUrl(target, this.integration.config);\n }\n\n // convert urls of the form:\n // https://example.com/<namespace>/<project>/-/jobs/artifacts/<ref>/raw/<path_to_file>?job=<job_name>\n // to urls of the form:\n // https://example.com/api/v4/projects/:id/jobs/artifacts/:ref_name/raw/*artifact_path?job=<job_name>\n private async getGitlabArtifactFetchUrl(target: URL): Promise<URL> {\n if (!target.pathname.includes('/-/jobs/artifacts/')) {\n throw new Error('Unable to process url as an GitLab artifact');\n }\n try {\n const [namespaceAndProject, ref] =\n target.pathname.split('/-/jobs/artifacts/');\n const projectPath = new URL(target);\n projectPath.pathname = namespaceAndProject;\n const projectId = await this.resolveProjectToId(projectPath);\n const relativePath = getGitLabIntegrationRelativePath(\n this.integration.config,\n );\n const newUrl = new URL(target);\n newUrl.pathname = `${relativePath}/api/v4/projects/${projectId}/jobs/artifacts/${ref}`;\n return newUrl;\n } catch (e) {\n throw new Error(\n `Unable to translate GitLab artifact URL: ${target}, ${e}`,\n );\n }\n }\n\n private async resolveProjectToId(pathToProject: URL): Promise<number> {\n let project = pathToProject.pathname;\n // Check relative path exist and remove it if so\n const relativePath = getGitLabIntegrationRelativePath(\n this.integration.config,\n );\n if (relativePath) {\n project = project.replace(relativePath, '');\n }\n // Trim an initial / if it exists\n project = project.replace(/^\\//, '');\n const result = await fetch(\n `${\n pathToProject.origin\n }${relativePath}/api/v4/projects/${encodeURIComponent(project)}`,\n getGitLabRequestOptions(this.integration.config),\n );\n const data = await result.json();\n if (!result.ok) {\n throw new Error(`Gitlab error: ${data.error}, ${data.error_description}`);\n }\n return Number(data.id);\n }\n}\n"],"names":["ScmIntegrations","fetch","getGitLabRequestOptions","NotModifiedError","ReadUrlResponseFactory","parseLastModified","NotFoundError","parseGitUrl","getGitLabIntegrationRelativePath","trimStart","Readable","Minimatch","trimEnd","getGitLabFileFetchUrl"],"mappings":"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"}
|
package/dist/package.json.cjs.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var name = "@backstage/backend-defaults";
|
|
6
|
-
var version = "0.5.
|
|
6
|
+
var version = "0.5.2";
|
|
7
7
|
var description = "Backend defaults used by Backstage backend apps";
|
|
8
8
|
var backstage = {
|
|
9
9
|
role: "node-library"
|
package/dist/urlReader.d.ts
CHANGED
|
@@ -256,8 +256,7 @@ declare class GitlabUrlReader implements UrlReaderService {
|
|
|
256
256
|
*
|
|
257
257
|
* E.g. `catalog/foo/*.yaml` will return `catalog/foo`.
|
|
258
258
|
*
|
|
259
|
-
* @param globPattern the glob pattern
|
|
260
|
-
* @private
|
|
259
|
+
* @param globPattern - the glob pattern
|
|
261
260
|
*/
|
|
262
261
|
private getStaticPart;
|
|
263
262
|
toString(): string;
|
package/httpAuth/package.json
CHANGED
package/httpRouter/package.json
CHANGED
package/lifecycle/package.json
CHANGED
package/logger/package.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/backend-defaults",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "Backend defaults used by Backstage backend apps",
|
|
5
5
|
"backstage": {
|
|
6
6
|
"role": "node-library"
|
|
@@ -150,21 +150,21 @@
|
|
|
150
150
|
"@aws-sdk/client-s3": "^3.350.0",
|
|
151
151
|
"@aws-sdk/credential-providers": "^3.350.0",
|
|
152
152
|
"@aws-sdk/types": "^3.347.0",
|
|
153
|
-
"@backstage/backend-app-api": "1.0.1
|
|
153
|
+
"@backstage/backend-app-api": "^1.0.1",
|
|
154
154
|
"@backstage/backend-common": "^0.25.0",
|
|
155
|
-
"@backstage/backend-dev-utils": "0.1.5",
|
|
156
|
-
"@backstage/backend-plugin-api": "1.0.1
|
|
157
|
-
"@backstage/cli-common": "0.1.14",
|
|
158
|
-
"@backstage/cli-node": "0.2.9
|
|
159
|
-
"@backstage/config": "1.2.0",
|
|
160
|
-
"@backstage/config-loader": "1.9.1",
|
|
161
|
-
"@backstage/errors": "1.2.4",
|
|
162
|
-
"@backstage/integration": "1.15.1
|
|
163
|
-
"@backstage/integration-aws-node": "0.1.12",
|
|
164
|
-
"@backstage/plugin-auth-node": "0.5.3
|
|
165
|
-
"@backstage/plugin-events-node": "0.4.
|
|
166
|
-
"@backstage/plugin-permission-node": "0.8.4
|
|
167
|
-
"@backstage/types": "1.1.1",
|
|
155
|
+
"@backstage/backend-dev-utils": "^0.1.5",
|
|
156
|
+
"@backstage/backend-plugin-api": "^1.0.1",
|
|
157
|
+
"@backstage/cli-common": "^0.1.14",
|
|
158
|
+
"@backstage/cli-node": "^0.2.9",
|
|
159
|
+
"@backstage/config": "^1.2.0",
|
|
160
|
+
"@backstage/config-loader": "^1.9.1",
|
|
161
|
+
"@backstage/errors": "^1.2.4",
|
|
162
|
+
"@backstage/integration": "^1.15.1",
|
|
163
|
+
"@backstage/integration-aws-node": "^0.1.12",
|
|
164
|
+
"@backstage/plugin-auth-node": "^0.5.3",
|
|
165
|
+
"@backstage/plugin-events-node": "^0.4.2",
|
|
166
|
+
"@backstage/plugin-permission-node": "^0.8.4",
|
|
167
|
+
"@backstage/types": "^1.1.1",
|
|
168
168
|
"@google-cloud/storage": "^7.0.0",
|
|
169
169
|
"@keyv/memcache": "^1.3.5",
|
|
170
170
|
"@keyv/redis": "^2.5.3",
|
|
@@ -218,9 +218,9 @@
|
|
|
218
218
|
},
|
|
219
219
|
"devDependencies": {
|
|
220
220
|
"@aws-sdk/util-stream-node": "^3.350.0",
|
|
221
|
-
"@backstage/backend-plugin-api": "1.0.1
|
|
222
|
-
"@backstage/backend-test-utils": "1.0.
|
|
223
|
-
"@backstage/cli": "0.28.0
|
|
221
|
+
"@backstage/backend-plugin-api": "^1.0.1",
|
|
222
|
+
"@backstage/backend-test-utils": "^1.0.2",
|
|
223
|
+
"@backstage/cli": "^0.28.0",
|
|
224
224
|
"@types/archiver": "^6.0.0",
|
|
225
225
|
"@types/base64-stream": "^1.0.2",
|
|
226
226
|
"@types/concat-stream": "^2.0.0",
|
package/permissions/package.json
CHANGED
package/rootConfig/package.json
CHANGED
package/rootHealth/package.json
CHANGED
package/rootLogger/package.json
CHANGED
package/scheduler/package.json
CHANGED
package/urlReader/package.json
CHANGED