@backstage/backend-defaults 0.6.0-next.0 → 0.6.0-next.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +58 -0
- package/config.d.ts +74 -1
- package/dist/entrypoints/auth/authServiceFactory.cjs.js +3 -2
- package/dist/entrypoints/auth/authServiceFactory.cjs.js.map +1 -1
- package/dist/entrypoints/auth/plugin/PluginTokenHandler.cjs.js +2 -1
- package/dist/entrypoints/auth/plugin/PluginTokenHandler.cjs.js.map +1 -1
- package/dist/entrypoints/auth/user/UserTokenHandler.cjs.js +5 -3
- package/dist/entrypoints/auth/user/UserTokenHandler.cjs.js.map +1 -1
- package/dist/entrypoints/database/connectors/postgres.cjs.js +40 -6
- package/dist/entrypoints/database/connectors/postgres.cjs.js.map +1 -1
- package/dist/entrypoints/httpRouter/httpRouterServiceFactory.cjs.js +3 -4
- package/dist/entrypoints/httpRouter/httpRouterServiceFactory.cjs.js.map +1 -1
- package/dist/entrypoints/rootHealth/rootHealthServiceFactory.cjs.js +11 -5
- package/dist/entrypoints/rootHealth/rootHealthServiceFactory.cjs.js.map +1 -1
- package/dist/entrypoints/rootHttpRouter/createHealthRouter.cjs.js +23 -0
- package/dist/entrypoints/rootHttpRouter/createHealthRouter.cjs.js.map +1 -1
- package/dist/entrypoints/rootHttpRouter/createLifecycleMiddleware.cjs.js +64 -0
- package/dist/entrypoints/rootHttpRouter/createLifecycleMiddleware.cjs.js.map +1 -0
- package/dist/entrypoints/rootHttpRouter/http/createHttpServer.cjs.js +1 -7
- package/dist/entrypoints/rootHttpRouter/http/createHttpServer.cjs.js.map +1 -1
- package/dist/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.cjs.js +27 -6
- package/dist/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.cjs.js.map +1 -1
- package/dist/entrypoints/rootLifecycle/rootLifecycleServiceFactory.cjs.js +29 -0
- package/dist/entrypoints/rootLifecycle/rootLifecycleServiceFactory.cjs.js.map +1 -1
- package/dist/entrypoints/rootLogger/WinstonLogger.cjs.js +9 -3
- package/dist/entrypoints/rootLogger/WinstonLogger.cjs.js.map +1 -1
- package/dist/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.cjs.js +15 -0
- package/dist/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/lib/AzureUrlReader.cjs.js +5 -11
- package/dist/entrypoints/urlReader/lib/AzureUrlReader.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/lib/BitbucketCloudUrlReader.cjs.js +5 -14
- package/dist/entrypoints/urlReader/lib/BitbucketCloudUrlReader.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/lib/BitbucketServerUrlReader.cjs.js +16 -14
- package/dist/entrypoints/urlReader/lib/BitbucketServerUrlReader.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/lib/BitbucketUrlReader.cjs.js +5 -14
- package/dist/entrypoints/urlReader/lib/BitbucketUrlReader.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/lib/FetchUrlReader.cjs.js +2 -10
- package/dist/entrypoints/urlReader/lib/FetchUrlReader.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/lib/GiteaUrlReader.cjs.js +4 -9
- package/dist/entrypoints/urlReader/lib/GiteaUrlReader.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/lib/GitlabUrlReader.cjs.js +7 -16
- package/dist/entrypoints/urlReader/lib/GitlabUrlReader.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/lib/ReadUrlResponseFactory.cjs.js +16 -2
- package/dist/entrypoints/urlReader/lib/ReadUrlResponseFactory.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/lib/tree/ReadTreeResponseFactory.cjs.js +23 -4
- package/dist/entrypoints/urlReader/lib/tree/ReadTreeResponseFactory.cjs.js.map +1 -1
- package/dist/entrypoints/urlReader/lib/util.cjs.js +29 -1
- package/dist/entrypoints/urlReader/lib/util.cjs.js.map +1 -1
- package/dist/entrypoints/userInfo/DefaultUserInfoService.cjs.js +1 -6
- package/dist/entrypoints/userInfo/DefaultUserInfoService.cjs.js.map +1 -1
- package/dist/package.json.cjs.js +16 -3
- package/dist/package.json.cjs.js.map +1 -1
- package/dist/rootHttpRouter.d.ts +3 -1
- package/dist/urlReader.d.ts +17 -2
- package/package.json +26 -17
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FetchUrlReader.cjs.js","sources":["../../../../src/entrypoints/urlReader/lib/FetchUrlReader.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 UrlReaderServiceReadTreeResponse,\n UrlReaderServiceReadUrlOptions,\n UrlReaderServiceReadUrlResponse,\n UrlReaderServiceSearchResponse,\n} from '@backstage/backend-plugin-api';\nimport { NotFoundError, NotModifiedError } from '@backstage/errors';\nimport fetch, { Response } from 'node-fetch';\nimport { ReaderFactory } from './types';\nimport path from 'path';\nimport { ReadUrlResponseFactory } from './ReadUrlResponseFactory';\nimport { parseLastModified } from './util';\n\nconst isInRange = (num: number, [start, end]: [number, number]) => {\n return num >= start && num <= end;\n};\n\nconst parsePortRange = (port: string): [number, number] => {\n const isRange = port.includes('-');\n if (isRange) {\n const range = port\n .split('-')\n .map(v => parseInt(v, 10))\n .filter(Boolean) as [number, number];\n if (range.length !== 2) throw new Error(`Port range is not valid: ${port}`);\n const [start, end] = range;\n if (start <= 0 || end <= 0 || start > end)\n throw new Error(`Port range is not valid: [${start}, ${end}]`);\n return range;\n }\n const parsedPort = parseInt(port, 10);\n return [parsedPort, parsedPort];\n};\n\nconst parsePortPredicate = (port: string | undefined) => {\n if (port) {\n const range = parsePortRange(port);\n return (url: URL) => {\n if (url.port) return isInRange(parseInt(url.port, 10), range);\n\n if (url.protocol === 'http:') return isInRange(80, range);\n if (url.protocol === 'https:') return isInRange(443, range);\n return false;\n };\n }\n return (url: URL) => !url.port;\n};\n\n/**\n * A {@link @backstage/backend-plugin-api#UrlReaderService} that does a plain fetch of the URL.\n *\n * @public\n */\nexport class FetchUrlReader implements UrlReaderService {\n /**\n * The factory creates a single reader that will be used for reading any URL that's listed\n * in configuration at `backend.reading.allow`. The allow list contains a list of objects describing\n * targets to allow, containing the following fields:\n *\n * `host`:\n * Either full hostnames to match, or subdomain wildcard matchers with a leading '*'.\n * For example 'example.com' and '*.example.com' are valid values, 'prod.*.example.com' is not.\n *\n * `paths`:\n * An optional list of paths which are allowed. If the list is omitted all paths are allowed.\n */\n static factory: ReaderFactory = ({ config }) => {\n const predicates =\n config\n .getOptionalConfigArray('backend.reading.allow')\n ?.map(allowConfig => {\n const paths = allowConfig.getOptionalStringArray('paths');\n const checkPath = paths\n ? (url: URL) => {\n const targetPath = path.posix.normalize(url.pathname);\n return paths.some(allowedPath =>\n targetPath.startsWith(allowedPath),\n );\n }\n : (_url: URL) => true;\n const host = allowConfig.getString('host');\n const [hostname, port] = host.split(':');\n\n const checkPort = parsePortPredicate(port);\n\n if (hostname.startsWith('*.')) {\n const suffix = hostname.slice(1);\n return (url: URL) =>\n url.hostname.endsWith(suffix) && checkPath(url) && checkPort(url);\n }\n return (url: URL) =>\n url.hostname === hostname && checkPath(url) && checkPort(url);\n }) ?? [];\n\n const reader = new FetchUrlReader();\n const predicate = (url: URL) => predicates.some(p => p(url));\n return [{ reader, predicate }];\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 let response: Response;\n try {\n response = await fetch(url, {\n headers: {\n ...(options?.etag && { 'If-None-Match': options.etag }),\n ...(options?.lastModifiedAfter && {\n 'If-Modified-Since': options.lastModifiedAfter.toUTCString(),\n }),\n ...(options?.token && { Authorization: `Bearer ${options.token}` }),\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\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: options?.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 = `could not read ${url}, ${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(): Promise<UrlReaderServiceReadTreeResponse> {\n throw new Error('FetchUrlReader does not implement readTree');\n }\n\n async search(): Promise<UrlReaderServiceSearchResponse> {\n throw new Error('FetchUrlReader does not implement search');\n }\n\n toString() {\n return 'fetch{}';\n }\n}\n"],"names":["path","fetch","NotModifiedError","ReadUrlResponseFactory","parseLastModified","NotFoundError"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FetchUrlReader.cjs.js","sources":["../../../../src/entrypoints/urlReader/lib/FetchUrlReader.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 UrlReaderServiceReadTreeResponse,\n UrlReaderServiceReadUrlOptions,\n UrlReaderServiceReadUrlResponse,\n UrlReaderServiceSearchResponse,\n} from '@backstage/backend-plugin-api';\nimport { NotFoundError, NotModifiedError } from '@backstage/errors';\nimport { ReaderFactory } from './types';\nimport path from 'path';\nimport { ReadUrlResponseFactory } from './ReadUrlResponseFactory';\n\nconst isInRange = (num: number, [start, end]: [number, number]) => {\n return num >= start && num <= end;\n};\n\nconst parsePortRange = (port: string): [number, number] => {\n const isRange = port.includes('-');\n if (isRange) {\n const range = port\n .split('-')\n .map(v => parseInt(v, 10))\n .filter(Boolean) as [number, number];\n if (range.length !== 2) throw new Error(`Port range is not valid: ${port}`);\n const [start, end] = range;\n if (start <= 0 || end <= 0 || start > end)\n throw new Error(`Port range is not valid: [${start}, ${end}]`);\n return range;\n }\n const parsedPort = parseInt(port, 10);\n return [parsedPort, parsedPort];\n};\n\nconst parsePortPredicate = (port: string | undefined) => {\n if (port) {\n const range = parsePortRange(port);\n return (url: URL) => {\n if (url.port) return isInRange(parseInt(url.port, 10), range);\n\n if (url.protocol === 'http:') return isInRange(80, range);\n if (url.protocol === 'https:') return isInRange(443, range);\n return false;\n };\n }\n return (url: URL) => !url.port;\n};\n\n/**\n * A {@link @backstage/backend-plugin-api#UrlReaderService} that does a plain fetch of the URL.\n *\n * @public\n */\nexport class FetchUrlReader implements UrlReaderService {\n /**\n * The factory creates a single reader that will be used for reading any URL that's listed\n * in configuration at `backend.reading.allow`. The allow list contains a list of objects describing\n * targets to allow, containing the following fields:\n *\n * `host`:\n * Either full hostnames to match, or subdomain wildcard matchers with a leading '*'.\n * For example 'example.com' and '*.example.com' are valid values, 'prod.*.example.com' is not.\n *\n * `paths`:\n * An optional list of paths which are allowed. If the list is omitted all paths are allowed.\n */\n static factory: ReaderFactory = ({ config }) => {\n const predicates =\n config\n .getOptionalConfigArray('backend.reading.allow')\n ?.map(allowConfig => {\n const paths = allowConfig.getOptionalStringArray('paths');\n const checkPath = paths\n ? (url: URL) => {\n const targetPath = path.posix.normalize(url.pathname);\n return paths.some(allowedPath =>\n targetPath.startsWith(allowedPath),\n );\n }\n : (_url: URL) => true;\n const host = allowConfig.getString('host');\n const [hostname, port] = host.split(':');\n\n const checkPort = parsePortPredicate(port);\n\n if (hostname.startsWith('*.')) {\n const suffix = hostname.slice(1);\n return (url: URL) =>\n url.hostname.endsWith(suffix) && checkPath(url) && checkPort(url);\n }\n return (url: URL) =>\n url.hostname === hostname && checkPath(url) && checkPort(url);\n }) ?? [];\n\n const reader = new FetchUrlReader();\n const predicate = (url: URL) => predicates.some(p => p(url));\n return [{ reader, predicate }];\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 let response: Response;\n try {\n response = await fetch(url, {\n headers: {\n ...(options?.etag && { 'If-None-Match': options.etag }),\n ...(options?.lastModifiedAfter && {\n 'If-Modified-Since': options.lastModifiedAfter.toUTCString(),\n }),\n ...(options?.token && { Authorization: `Bearer ${options.token}` }),\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\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: options?.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.fromResponse(response);\n }\n\n const message = `could not read ${url}, ${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(): Promise<UrlReaderServiceReadTreeResponse> {\n throw new Error('FetchUrlReader does not implement readTree');\n }\n\n async search(): Promise<UrlReaderServiceSearchResponse> {\n throw new Error('FetchUrlReader does not implement search');\n }\n\n toString() {\n return 'fetch{}';\n }\n}\n"],"names":["path","NotModifiedError","ReadUrlResponseFactory","NotFoundError"],"mappings":"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"}
|
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var integration = require('@backstage/integration');
|
|
4
|
-
var fetch = require('node-fetch');
|
|
5
4
|
var ReadUrlResponseFactory = require('./ReadUrlResponseFactory.cjs.js');
|
|
6
5
|
var errors = require('@backstage/errors');
|
|
7
6
|
var stream = require('stream');
|
|
8
7
|
var util = require('./util.cjs.js');
|
|
9
8
|
|
|
10
|
-
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
11
|
-
|
|
12
|
-
var fetch__default = /*#__PURE__*/_interopDefaultCompat(fetch);
|
|
13
|
-
|
|
14
9
|
class GiteaUrlReader {
|
|
15
10
|
constructor(integration, deps) {
|
|
16
11
|
this.integration = integration;
|
|
@@ -33,7 +28,7 @@ class GiteaUrlReader {
|
|
|
33
28
|
let response;
|
|
34
29
|
const blobUrl = integration.getGiteaFileContentsUrl(this.integration.config, url);
|
|
35
30
|
try {
|
|
36
|
-
response = await
|
|
31
|
+
response = await fetch(blobUrl, {
|
|
37
32
|
method: "GET",
|
|
38
33
|
...integration.getGiteaRequestOptions(this.integration.config),
|
|
39
34
|
signal: options?.signal
|
|
@@ -76,7 +71,7 @@ class GiteaUrlReader {
|
|
|
76
71
|
const archiveUri = integration.getGiteaArchiveUrl(this.integration.config, url);
|
|
77
72
|
let response;
|
|
78
73
|
try {
|
|
79
|
-
response = await
|
|
74
|
+
response = await fetch(archiveUri, {
|
|
80
75
|
method: "GET",
|
|
81
76
|
...integration.getGiteaRequestOptions(this.integration.config),
|
|
82
77
|
signal: options?.signal
|
|
@@ -86,7 +81,7 @@ class GiteaUrlReader {
|
|
|
86
81
|
}
|
|
87
82
|
const parsedUri = integration.parseGiteaUrl(this.integration.config, url);
|
|
88
83
|
return this.deps.treeResponseFactory.fromTarArchive({
|
|
89
|
-
|
|
84
|
+
response,
|
|
90
85
|
subpath: parsedUri.path,
|
|
91
86
|
etag: lastCommitHash,
|
|
92
87
|
filter: options?.filter
|
|
@@ -103,7 +98,7 @@ class GiteaUrlReader {
|
|
|
103
98
|
}
|
|
104
99
|
async getLastCommitHash(url) {
|
|
105
100
|
const commitUri = integration.getGiteaLatestCommitUrl(this.integration.config, url);
|
|
106
|
-
const response = await
|
|
101
|
+
const response = await fetch(
|
|
107
102
|
commitUri,
|
|
108
103
|
integration.getGiteaRequestOptions(this.integration.config)
|
|
109
104
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GiteaUrlReader.cjs.js","sources":["../../../../src/entrypoints/urlReader/lib/GiteaUrlReader.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 UrlReaderService,\n UrlReaderServiceReadTreeOptions,\n UrlReaderServiceReadTreeResponse,\n UrlReaderServiceReadUrlOptions,\n UrlReaderServiceReadUrlResponse,\n UrlReaderServiceSearchResponse,\n} from '@backstage/backend-plugin-api';\nimport {\n getGiteaFileContentsUrl,\n getGiteaArchiveUrl,\n getGiteaLatestCommitUrl,\n parseGiteaUrl,\n getGiteaRequestOptions,\n GiteaIntegration,\n ScmIntegrations,\n} from '@backstage/integration';\nimport { ReaderFactory, ReadTreeResponseFactory } from './types';\nimport
|
|
1
|
+
{"version":3,"file":"GiteaUrlReader.cjs.js","sources":["../../../../src/entrypoints/urlReader/lib/GiteaUrlReader.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 UrlReaderService,\n UrlReaderServiceReadTreeOptions,\n UrlReaderServiceReadTreeResponse,\n UrlReaderServiceReadUrlOptions,\n UrlReaderServiceReadUrlResponse,\n UrlReaderServiceSearchResponse,\n} from '@backstage/backend-plugin-api';\nimport {\n getGiteaFileContentsUrl,\n getGiteaArchiveUrl,\n getGiteaLatestCommitUrl,\n parseGiteaUrl,\n getGiteaRequestOptions,\n GiteaIntegration,\n ScmIntegrations,\n} from '@backstage/integration';\nimport { ReaderFactory, ReadTreeResponseFactory } from './types';\nimport { ReadUrlResponseFactory } from './ReadUrlResponseFactory';\nimport {\n AuthenticationError,\n NotFoundError,\n NotModifiedError,\n} from '@backstage/errors';\nimport { Readable } from 'stream';\nimport { parseLastModified } from './util';\n\n/**\n * Implements a {@link @backstage/backend-plugin-api#UrlReaderService} for the Gitea v1 api.\n *\n * @public\n */\nexport class GiteaUrlReader implements UrlReaderService {\n static factory: ReaderFactory = ({ config, treeResponseFactory }) => {\n return ScmIntegrations.fromConfig(config)\n .gitea.list()\n .map(integration => {\n const reader = new GiteaUrlReader(integration, { treeResponseFactory });\n const predicate = (url: URL) => {\n return url.host === integration.config.host;\n };\n return { reader, predicate };\n });\n };\n\n constructor(\n private readonly integration: GiteaIntegration,\n private readonly deps: {\n treeResponseFactory: ReadTreeResponseFactory;\n },\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 let response: Response;\n const blobUrl = getGiteaFileContentsUrl(this.integration.config, url);\n\n try {\n response = await fetch(blobUrl, {\n method: 'GET',\n ...getGiteaRequestOptions(this.integration.config),\n signal: options?.signal as any,\n });\n } catch (e) {\n throw new Error(`Unable to read ${blobUrl}, ${e}`);\n }\n\n if (response.ok) {\n // Gitea returns an object with the file contents encoded, not the file itself\n const { encoding, content } = await response.json();\n\n if (encoding === 'base64') {\n return ReadUrlResponseFactory.fromReadable(\n Readable.from(Buffer.from(content, 'base64')),\n {\n etag: response.headers.get('ETag') ?? undefined,\n lastModifiedAt: parseLastModified(\n response.headers.get('Last-Modified'),\n ),\n },\n );\n }\n\n throw new Error(`Unknown encoding: ${encoding}`);\n }\n\n const message = `${url} could not be read as ${blobUrl}, ${response.status} ${response.statusText}`;\n if (response.status === 404) {\n throw new NotFoundError(message);\n }\n\n if (response.status === 304) {\n throw new NotModifiedError();\n }\n\n if (response.status === 403) {\n throw new AuthenticationError();\n }\n\n throw new Error(message);\n }\n\n async readTree(\n url: string,\n options?: UrlReaderServiceReadTreeOptions,\n ): Promise<UrlReaderServiceReadTreeResponse> {\n const lastCommitHash = await this.getLastCommitHash(url);\n if (options?.etag && options.etag === lastCommitHash) {\n throw new NotModifiedError();\n }\n\n const archiveUri = getGiteaArchiveUrl(this.integration.config, url);\n\n let response: Response;\n try {\n response = await fetch(archiveUri, {\n method: 'GET',\n ...getGiteaRequestOptions(this.integration.config),\n signal: options?.signal as any,\n });\n } catch (e) {\n throw new Error(`Unable to read ${archiveUri}, ${e}`);\n }\n\n const parsedUri = parseGiteaUrl(this.integration.config, url);\n\n return this.deps.treeResponseFactory.fromTarArchive({\n response: response,\n subpath: parsedUri.path,\n etag: lastCommitHash,\n filter: options?.filter,\n });\n }\n\n search(): Promise<UrlReaderServiceSearchResponse> {\n throw new Error('GiteaUrlReader search not implemented.');\n }\n\n toString() {\n const { host } = this.integration.config;\n return `gitea{host=${host},authed=${Boolean(\n this.integration.config.password,\n )}}`;\n }\n\n private async getLastCommitHash(url: string): Promise<string> {\n const commitUri = getGiteaLatestCommitUrl(this.integration.config, url);\n\n const response = await fetch(\n commitUri,\n getGiteaRequestOptions(this.integration.config),\n );\n if (!response.ok) {\n const message = `Failed to retrieve latest commit information from ${commitUri}, ${response.status} ${response.statusText}`;\n if (response.status === 404) {\n throw new NotFoundError(message);\n }\n throw new Error(message);\n }\n\n return (await response.json()).sha;\n }\n}\n"],"names":["ScmIntegrations","getGiteaFileContentsUrl","getGiteaRequestOptions","ReadUrlResponseFactory","Readable","parseLastModified","NotFoundError","NotModifiedError","AuthenticationError","getGiteaArchiveUrl","parseGiteaUrl","getGiteaLatestCommitUrl"],"mappings":"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"}
|
|
@@ -5,15 +5,11 @@ var integration = require('@backstage/integration');
|
|
|
5
5
|
var parseGitUrl = require('git-url-parse');
|
|
6
6
|
var lodash = require('lodash');
|
|
7
7
|
var minimatch = require('minimatch');
|
|
8
|
-
var fetch = require('node-fetch');
|
|
9
|
-
var stream = require('stream');
|
|
10
8
|
var ReadUrlResponseFactory = require('./ReadUrlResponseFactory.cjs.js');
|
|
11
|
-
var util = require('./util.cjs.js');
|
|
12
9
|
|
|
13
10
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
14
11
|
|
|
15
12
|
var parseGitUrl__default = /*#__PURE__*/_interopDefaultCompat(parseGitUrl);
|
|
16
|
-
var fetch__default = /*#__PURE__*/_interopDefaultCompat(fetch);
|
|
17
13
|
|
|
18
14
|
class GitlabUrlReader {
|
|
19
15
|
constructor(integration, deps) {
|
|
@@ -39,7 +35,7 @@ class GitlabUrlReader {
|
|
|
39
35
|
const builtUrl = await this.getGitlabFetchUrl(url);
|
|
40
36
|
let response;
|
|
41
37
|
try {
|
|
42
|
-
response = await
|
|
38
|
+
response = await fetch(builtUrl, {
|
|
43
39
|
headers: {
|
|
44
40
|
...integration.getGitLabRequestOptions(this.integration.config, token).headers,
|
|
45
41
|
...etag && { "If-None-Match": etag },
|
|
@@ -62,12 +58,7 @@ class GitlabUrlReader {
|
|
|
62
58
|
throw new errors.NotModifiedError();
|
|
63
59
|
}
|
|
64
60
|
if (response.ok) {
|
|
65
|
-
return ReadUrlResponseFactory.ReadUrlResponseFactory.
|
|
66
|
-
etag: response.headers.get("ETag") ?? void 0,
|
|
67
|
-
lastModifiedAt: util.parseLastModified(
|
|
68
|
-
response.headers.get("Last-Modified")
|
|
69
|
-
)
|
|
70
|
-
});
|
|
61
|
+
return ReadUrlResponseFactory.ReadUrlResponseFactory.fromResponse(response);
|
|
71
62
|
}
|
|
72
63
|
const message = `${url} could not be read as ${builtUrl}, ${response.status} ${response.statusText}`;
|
|
73
64
|
if (response.status === 404) {
|
|
@@ -86,7 +77,7 @@ class GitlabUrlReader {
|
|
|
86
77
|
const rectifiedRelativePath = `${lodash.trimStart(relativePath, "/")}/`;
|
|
87
78
|
repoFullName = full_name.replace(rectifiedRelativePath, "");
|
|
88
79
|
}
|
|
89
|
-
const projectGitlabResponse = await
|
|
80
|
+
const projectGitlabResponse = await fetch(
|
|
90
81
|
new URL(
|
|
91
82
|
`${this.integration.config.apiBaseUrl}/projects/${encodeURIComponent(
|
|
92
83
|
repoFullName
|
|
@@ -108,7 +99,7 @@ class GitlabUrlReader {
|
|
|
108
99
|
if (!!filepath) {
|
|
109
100
|
commitsReqParams.set("path", filepath);
|
|
110
101
|
}
|
|
111
|
-
const commitsGitlabResponse = await
|
|
102
|
+
const commitsGitlabResponse = await fetch(
|
|
112
103
|
new URL(
|
|
113
104
|
`${this.integration.config.apiBaseUrl}/projects/${encodeURIComponent(
|
|
114
105
|
repoFullName
|
|
@@ -141,7 +132,7 @@ class GitlabUrlReader {
|
|
|
141
132
|
if (!!filepath) {
|
|
142
133
|
archiveReqParams.set("path", filepath);
|
|
143
134
|
}
|
|
144
|
-
const archiveGitLabResponse = await
|
|
135
|
+
const archiveGitLabResponse = await fetch(
|
|
145
136
|
`${this.integration.config.apiBaseUrl}/projects/${encodeURIComponent(
|
|
146
137
|
repoFullName
|
|
147
138
|
)}/repository/archive?${archiveReqParams.toString()}`,
|
|
@@ -164,7 +155,7 @@ class GitlabUrlReader {
|
|
|
164
155
|
throw new Error(message);
|
|
165
156
|
}
|
|
166
157
|
return await this.deps.treeResponseFactory.fromTarArchive({
|
|
167
|
-
|
|
158
|
+
response: archiveGitLabResponse,
|
|
168
159
|
subpath: filepath,
|
|
169
160
|
etag: commitSha,
|
|
170
161
|
filter: options?.filter
|
|
@@ -260,7 +251,7 @@ class GitlabUrlReader {
|
|
|
260
251
|
project = project.replace(relativePath, "");
|
|
261
252
|
}
|
|
262
253
|
project = project.replace(/^\//, "");
|
|
263
|
-
const result = await
|
|
254
|
+
const result = await fetch(
|
|
264
255
|
`${pathToProject.origin}${relativePath}/api/v4/projects/${encodeURIComponent(project)}`,
|
|
265
256
|
integration.getGitLabRequestOptions(this.integration.config)
|
|
266
257
|
);
|
|
@@ -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 */\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 { ReadUrlResponseFactory } from './ReadUrlResponseFactory';\nimport { ReadTreeResponseFactory, ReaderFactory } from './types';\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.fromResponse(response);\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 response: archiveGitLabResponse,\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","getGitLabRequestOptions","NotModifiedError","ReadUrlResponseFactory","NotFoundError","parseGitUrl","getGitLabIntegrationRelativePath","trimStart","Minimatch","trimEnd","getGitLabFileFetchUrl"],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
var errors = require('@backstage/errors');
|
|
4
4
|
var getRawBody = require('raw-body');
|
|
5
5
|
var stream = require('stream');
|
|
6
|
+
var util = require('./util.cjs.js');
|
|
6
7
|
|
|
7
8
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
8
9
|
|
|
@@ -10,7 +11,7 @@ var getRawBody__default = /*#__PURE__*/_interopDefaultCompat(getRawBody);
|
|
|
10
11
|
|
|
11
12
|
class ReadUrlResponseFactory {
|
|
12
13
|
/**
|
|
13
|
-
* Resolves a
|
|
14
|
+
* Resolves a UrlReaderServiceReadUrlResponse from a Readable stream.
|
|
14
15
|
*/
|
|
15
16
|
static async fromReadable(stream, options) {
|
|
16
17
|
let buffer;
|
|
@@ -37,12 +38,25 @@ class ReadUrlResponseFactory {
|
|
|
37
38
|
};
|
|
38
39
|
}
|
|
39
40
|
/**
|
|
40
|
-
* Resolves a
|
|
41
|
+
* Resolves a UrlReaderServiceReadUrlResponse from an old-style NodeJS.ReadableStream.
|
|
41
42
|
*/
|
|
42
43
|
static async fromNodeJSReadable(oldStyleStream, options) {
|
|
43
44
|
const readable = stream.Readable.from(oldStyleStream);
|
|
44
45
|
return ReadUrlResponseFactory.fromReadable(readable, options);
|
|
45
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Resolves a UrlReaderServiceReadUrlResponse from a native fetch response body.
|
|
49
|
+
*/
|
|
50
|
+
static async fromResponse(response) {
|
|
51
|
+
const etag = response.headers.get("etag") || void 0;
|
|
52
|
+
const lastModifiedAt = util.parseLastModified(
|
|
53
|
+
response.headers.get("last-modified")
|
|
54
|
+
);
|
|
55
|
+
return ReadUrlResponseFactory.fromReadable(util.responseToReadable(response), {
|
|
56
|
+
etag,
|
|
57
|
+
lastModifiedAt
|
|
58
|
+
});
|
|
59
|
+
}
|
|
46
60
|
}
|
|
47
61
|
|
|
48
62
|
exports.ReadUrlResponseFactory = ReadUrlResponseFactory;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReadUrlResponseFactory.cjs.js","sources":["../../../../src/entrypoints/urlReader/lib/ReadUrlResponseFactory.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 { ConflictError } from '@backstage/errors';\nimport { UrlReaderServiceReadUrlResponse } from '@backstage/backend-plugin-api';\nimport getRawBody from 'raw-body';\nimport { Readable } from 'stream';\nimport { ReadUrlResponseFactoryFromStreamOptions } from './types';\n\n/**\n * Utility class for UrlReader implementations to create valid ReadUrlResponse\n * instances from common response primitives.\n *\n * @public\n */\nexport class ReadUrlResponseFactory {\n /**\n * Resolves a
|
|
1
|
+
{"version":3,"file":"ReadUrlResponseFactory.cjs.js","sources":["../../../../src/entrypoints/urlReader/lib/ReadUrlResponseFactory.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 { ConflictError } from '@backstage/errors';\nimport { UrlReaderServiceReadUrlResponse } from '@backstage/backend-plugin-api';\nimport getRawBody from 'raw-body';\nimport { Readable } from 'stream';\nimport { ReadUrlResponseFactoryFromStreamOptions } from './types';\nimport { parseLastModified, responseToReadable } from './util';\n\n/**\n * Utility class for UrlReader implementations to create valid ReadUrlResponse\n * instances from common response primitives.\n *\n * @public\n */\nexport class ReadUrlResponseFactory {\n /**\n * Resolves a UrlReaderServiceReadUrlResponse from a Readable stream.\n */\n static async fromReadable(\n stream: Readable,\n options?: ReadUrlResponseFactoryFromStreamOptions,\n ): Promise<UrlReaderServiceReadUrlResponse> {\n // Reference to eventual buffer enables callers to call buffer() multiple\n // times without consequence.\n let buffer: Promise<Buffer>;\n\n // Prevent \"stream is not readable\" errors from bubbling up.\n const conflictError = new ConflictError(\n 'Cannot use buffer() and stream() from the same ReadUrlResponse',\n );\n let hasCalledStream = false;\n let hasCalledBuffer = false;\n\n return {\n buffer: () => {\n hasCalledBuffer = true;\n if (hasCalledStream) throw conflictError;\n if (buffer) return buffer;\n buffer = getRawBody(stream);\n return buffer;\n },\n stream: () => {\n hasCalledStream = true;\n if (hasCalledBuffer) throw conflictError;\n return stream;\n },\n etag: options?.etag,\n lastModifiedAt: options?.lastModifiedAt,\n };\n }\n\n /**\n * Resolves a UrlReaderServiceReadUrlResponse from an old-style NodeJS.ReadableStream.\n */\n static async fromNodeJSReadable(\n oldStyleStream: NodeJS.ReadableStream,\n options?: ReadUrlResponseFactoryFromStreamOptions,\n ): Promise<UrlReaderServiceReadUrlResponse> {\n const readable = Readable.from(oldStyleStream);\n return ReadUrlResponseFactory.fromReadable(readable, options);\n }\n\n /**\n * Resolves a UrlReaderServiceReadUrlResponse from a native fetch response body.\n */\n static async fromResponse(\n response: Response,\n ): Promise<UrlReaderServiceReadUrlResponse> {\n const etag = response.headers.get('etag') || undefined;\n const lastModifiedAt = parseLastModified(\n response.headers.get('last-modified'),\n );\n\n return ReadUrlResponseFactory.fromReadable(responseToReadable(response), {\n etag,\n lastModifiedAt,\n });\n }\n}\n"],"names":["ConflictError","getRawBody","Readable","parseLastModified","responseToReadable"],"mappings":";;;;;;;;;;;AA6BO,MAAM,sBAAuB,CAAA;AAAA;AAAA;AAAA;AAAA,EAIlC,aAAa,YACX,CAAA,MAAA,EACA,OAC0C,EAAA;AAG1C,IAAI,IAAA,MAAA;AAGJ,IAAA,MAAM,gBAAgB,IAAIA,oBAAA;AAAA,MACxB;AAAA,KACF;AACA,IAAA,IAAI,eAAkB,GAAA,KAAA;AACtB,IAAA,IAAI,eAAkB,GAAA,KAAA;AAEtB,IAAO,OAAA;AAAA,MACL,QAAQ,MAAM;AACZ,QAAkB,eAAA,GAAA,IAAA;AAClB,QAAA,IAAI,iBAAuB,MAAA,aAAA;AAC3B,QAAA,IAAI,QAAe,OAAA,MAAA;AACnB,QAAA,MAAA,GAASC,4BAAW,MAAM,CAAA;AAC1B,QAAO,OAAA,MAAA;AAAA,OACT;AAAA,MACA,QAAQ,MAAM;AACZ,QAAkB,eAAA,GAAA,IAAA;AAClB,QAAA,IAAI,iBAAuB,MAAA,aAAA;AAC3B,QAAO,OAAA,MAAA;AAAA,OACT;AAAA,MACA,MAAM,OAAS,EAAA,IAAA;AAAA,MACf,gBAAgB,OAAS,EAAA;AAAA,KAC3B;AAAA;AACF;AAAA;AAAA;AAAA,EAKA,aAAa,kBACX,CAAA,cAAA,EACA,OAC0C,EAAA;AAC1C,IAAM,MAAA,QAAA,GAAWC,eAAS,CAAA,IAAA,CAAK,cAAc,CAAA;AAC7C,IAAO,OAAA,sBAAA,CAAuB,YAAa,CAAA,QAAA,EAAU,OAAO,CAAA;AAAA;AAC9D;AAAA;AAAA;AAAA,EAKA,aAAa,aACX,QAC0C,EAAA;AAC1C,IAAA,MAAM,IAAO,GAAA,QAAA,CAAS,OAAQ,CAAA,GAAA,CAAI,MAAM,CAAK,IAAA,KAAA,CAAA;AAC7C,IAAA,MAAM,cAAiB,GAAAC,sBAAA;AAAA,MACrB,QAAA,CAAS,OAAQ,CAAA,GAAA,CAAI,eAAe;AAAA,KACtC;AAEA,IAAA,OAAO,sBAAuB,CAAA,YAAA,CAAaC,uBAAmB,CAAA,QAAQ,CAAG,EAAA;AAAA,MACvE,IAAA;AAAA,MACA;AAAA,KACD,CAAA;AAAA;AAEL;;;;"}
|
|
@@ -4,6 +4,7 @@ var os = require('os');
|
|
|
4
4
|
var TarArchiveResponse = require('./TarArchiveResponse.cjs.js');
|
|
5
5
|
var ZipArchiveResponse = require('./ZipArchiveResponse.cjs.js');
|
|
6
6
|
var ReadableArrayResponse = require('./ReadableArrayResponse.cjs.js');
|
|
7
|
+
var util = require('../util.cjs.js');
|
|
7
8
|
|
|
8
9
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
9
10
|
|
|
@@ -19,21 +20,39 @@ class DefaultReadTreeResponseFactory {
|
|
|
19
20
|
);
|
|
20
21
|
}
|
|
21
22
|
async fromTarArchive(options) {
|
|
23
|
+
let stream;
|
|
24
|
+
let etag;
|
|
25
|
+
if ("stream" in options) {
|
|
26
|
+
stream = options.stream;
|
|
27
|
+
etag = options.etag;
|
|
28
|
+
} else {
|
|
29
|
+
stream = util.responseToReadable(options.response);
|
|
30
|
+
etag = (options.etag ?? options.response.headers.get("etag")) || "";
|
|
31
|
+
}
|
|
22
32
|
return new TarArchiveResponse.TarArchiveResponse(
|
|
23
|
-
|
|
33
|
+
stream,
|
|
24
34
|
options.subpath ?? "",
|
|
25
35
|
this.workDir,
|
|
26
|
-
|
|
36
|
+
etag,
|
|
27
37
|
options.filter,
|
|
28
38
|
options.stripFirstDirectory ?? true
|
|
29
39
|
);
|
|
30
40
|
}
|
|
31
41
|
async fromZipArchive(options) {
|
|
42
|
+
let stream;
|
|
43
|
+
let etag;
|
|
44
|
+
if ("stream" in options) {
|
|
45
|
+
stream = options.stream;
|
|
46
|
+
etag = options.etag;
|
|
47
|
+
} else {
|
|
48
|
+
stream = util.responseToReadable(options.response);
|
|
49
|
+
etag = (options.etag ?? options.response.headers.get("etag")) || "";
|
|
50
|
+
}
|
|
32
51
|
return new ZipArchiveResponse.ZipArchiveResponse(
|
|
33
|
-
|
|
52
|
+
stream,
|
|
34
53
|
options.subpath ?? "",
|
|
35
54
|
this.workDir,
|
|
36
|
-
|
|
55
|
+
etag,
|
|
37
56
|
options.filter
|
|
38
57
|
);
|
|
39
58
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReadTreeResponseFactory.cjs.js","sources":["../../../../../src/entrypoints/urlReader/lib/tree/ReadTreeResponseFactory.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 os from 'os';\nimport { Config } from '@backstage/config';\nimport {\n ReadTreeResponseFactoryOptions,\n ReadTreeResponseFactory,\n FromReadableArrayOptions,\n} from '../types';\nimport { TarArchiveResponse } from './TarArchiveResponse';\nimport { ZipArchiveResponse } from './ZipArchiveResponse';\nimport { ReadableArrayResponse } from './ReadableArrayResponse';\nimport { UrlReaderServiceReadTreeResponse } from '@backstage/backend-plugin-api';\n\nexport class DefaultReadTreeResponseFactory implements ReadTreeResponseFactory {\n static create(options: { config: Config }): DefaultReadTreeResponseFactory {\n return new DefaultReadTreeResponseFactory(\n options.config.getOptionalString('backend.workingDirectory') ??\n os.tmpdir(),\n );\n }\n\n constructor(private readonly workDir: string) {}\n\n async fromTarArchive(\n options: ReadTreeResponseFactoryOptions & {\n stripFirstDirectory?: boolean;\n },\n ): Promise<UrlReaderServiceReadTreeResponse> {\n return new TarArchiveResponse(\n
|
|
1
|
+
{"version":3,"file":"ReadTreeResponseFactory.cjs.js","sources":["../../../../../src/entrypoints/urlReader/lib/tree/ReadTreeResponseFactory.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 os from 'os';\nimport { Readable } from 'stream';\nimport { Config } from '@backstage/config';\nimport {\n ReadTreeResponseFactoryOptions,\n ReadTreeResponseFactory,\n FromReadableArrayOptions,\n} from '../types';\nimport { TarArchiveResponse } from './TarArchiveResponse';\nimport { ZipArchiveResponse } from './ZipArchiveResponse';\nimport { ReadableArrayResponse } from './ReadableArrayResponse';\nimport { UrlReaderServiceReadTreeResponse } from '@backstage/backend-plugin-api';\nimport { responseToReadable } from '../util';\n\nexport class DefaultReadTreeResponseFactory implements ReadTreeResponseFactory {\n static create(options: { config: Config }): DefaultReadTreeResponseFactory {\n return new DefaultReadTreeResponseFactory(\n options.config.getOptionalString('backend.workingDirectory') ??\n os.tmpdir(),\n );\n }\n\n constructor(private readonly workDir: string) {}\n\n async fromTarArchive(\n options: ReadTreeResponseFactoryOptions & {\n stripFirstDirectory?: boolean;\n },\n ): Promise<UrlReaderServiceReadTreeResponse> {\n let stream: Readable;\n let etag: string;\n if ('stream' in options) {\n stream = options.stream;\n etag = options.etag;\n } else {\n stream = responseToReadable(options.response);\n etag = (options.etag ?? options.response.headers.get('etag')) || '';\n }\n\n return new TarArchiveResponse(\n stream,\n options.subpath ?? '',\n this.workDir,\n etag,\n options.filter,\n options.stripFirstDirectory ?? true,\n );\n }\n\n async fromZipArchive(\n options: ReadTreeResponseFactoryOptions,\n ): Promise<UrlReaderServiceReadTreeResponse> {\n let stream: Readable;\n let etag: string;\n if ('stream' in options) {\n stream = options.stream;\n etag = options.etag;\n } else {\n stream = responseToReadable(options.response);\n etag = (options.etag ?? options.response.headers.get('etag')) || '';\n }\n\n return new ZipArchiveResponse(\n stream,\n options.subpath ?? '',\n this.workDir,\n etag,\n options.filter,\n );\n }\n\n async fromReadableArray(\n options: FromReadableArrayOptions,\n ): Promise<UrlReaderServiceReadTreeResponse> {\n return new ReadableArrayResponse(options, this.workDir, '');\n }\n}\n"],"names":["os","responseToReadable","TarArchiveResponse","ZipArchiveResponse","ReadableArrayResponse"],"mappings":";;;;;;;;;;;;AA8BO,MAAM,8BAAkE,CAAA;AAAA,EAQ7E,YAA6B,OAAiB,EAAA;AAAjB,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAAA;AAAkB,EAP/C,OAAO,OAAO,OAA6D,EAAA;AACzE,IAAA,OAAO,IAAI,8BAAA;AAAA,MACT,QAAQ,MAAO,CAAA,iBAAA,CAAkB,0BAA0B,CAAA,IACzDA,oBAAG,MAAO;AAAA,KACd;AAAA;AACF,EAIA,MAAM,eACJ,OAG2C,EAAA;AAC3C,IAAI,IAAA,MAAA;AACJ,IAAI,IAAA,IAAA;AACJ,IAAA,IAAI,YAAY,OAAS,EAAA;AACvB,MAAA,MAAA,GAAS,OAAQ,CAAA,MAAA;AACjB,MAAA,IAAA,GAAO,OAAQ,CAAA,IAAA;AAAA,KACV,MAAA;AACL,MAAS,MAAA,GAAAC,uBAAA,CAAmB,QAAQ,QAAQ,CAAA;AAC5C,MAAA,IAAA,GAAA,CAAQ,QAAQ,IAAQ,IAAA,OAAA,CAAQ,SAAS,OAAQ,CAAA,GAAA,CAAI,MAAM,CAAM,KAAA,EAAA;AAAA;AAGnE,IAAA,OAAO,IAAIC,qCAAA;AAAA,MACT,MAAA;AAAA,MACA,QAAQ,OAAW,IAAA,EAAA;AAAA,MACnB,IAAK,CAAA,OAAA;AAAA,MACL,IAAA;AAAA,MACA,OAAQ,CAAA,MAAA;AAAA,MACR,QAAQ,mBAAuB,IAAA;AAAA,KACjC;AAAA;AACF,EAEA,MAAM,eACJ,OAC2C,EAAA;AAC3C,IAAI,IAAA,MAAA;AACJ,IAAI,IAAA,IAAA;AACJ,IAAA,IAAI,YAAY,OAAS,EAAA;AACvB,MAAA,MAAA,GAAS,OAAQ,CAAA,MAAA;AACjB,MAAA,IAAA,GAAO,OAAQ,CAAA,IAAA;AAAA,KACV,MAAA;AACL,MAAS,MAAA,GAAAD,uBAAA,CAAmB,QAAQ,QAAQ,CAAA;AAC5C,MAAA,IAAA,GAAA,CAAQ,QAAQ,IAAQ,IAAA,OAAA,CAAQ,SAAS,OAAQ,CAAA,GAAA,CAAI,MAAM,CAAM,KAAA,EAAA;AAAA;AAGnE,IAAA,OAAO,IAAIE,qCAAA;AAAA,MACT,MAAA;AAAA,MACA,QAAQ,OAAW,IAAA,EAAA;AAAA,MACnB,IAAK,CAAA,OAAA;AAAA,MACL,IAAA;AAAA,MACA,OAAQ,CAAA;AAAA,KACV;AAAA;AACF,EAEA,MAAM,kBACJ,OAC2C,EAAA;AAC3C,IAAA,OAAO,IAAIC,2CAAA,CAAsB,OAAS,EAAA,IAAA,CAAK,SAAS,EAAE,CAAA;AAAA;AAE9D;;;;"}
|
|
@@ -1,11 +1,39 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var stream = require('stream');
|
|
4
|
+
var web = require('stream/web');
|
|
5
|
+
|
|
3
6
|
function parseLastModified(value) {
|
|
4
7
|
if (!value) {
|
|
5
8
|
return void 0;
|
|
6
9
|
}
|
|
7
|
-
|
|
10
|
+
try {
|
|
11
|
+
const result = new Date(value);
|
|
12
|
+
result.toISOString();
|
|
13
|
+
return result;
|
|
14
|
+
} catch {
|
|
15
|
+
return void 0;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function responseToReadable(response) {
|
|
19
|
+
return response.body ? stream.Readable.from(toWeb(response.body)) : new stream.PassThrough().end();
|
|
20
|
+
}
|
|
21
|
+
function toWeb(responseBody) {
|
|
22
|
+
const reader = responseBody.getReader();
|
|
23
|
+
return new web.ReadableStream({
|
|
24
|
+
async pull(controller) {
|
|
25
|
+
const { value, done } = await reader.read();
|
|
26
|
+
if (value) {
|
|
27
|
+
controller.enqueue(value);
|
|
28
|
+
}
|
|
29
|
+
if (done) {
|
|
30
|
+
controller.close();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
});
|
|
8
34
|
}
|
|
9
35
|
|
|
10
36
|
exports.parseLastModified = parseLastModified;
|
|
37
|
+
exports.responseToReadable = responseToReadable;
|
|
38
|
+
exports.toWeb = toWeb;
|
|
11
39
|
//# sourceMappingURL=util.cjs.js.map
|
|
@@ -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\nexport function parseLastModified(value: string | null | undefined) {\n if (!value) {\n return undefined;\n }\n\n
|
|
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 'stream';\nimport { ReadableStream as WebReadableStream } from '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.\nexport function 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,KACkB,EAAA;AAClB,EAAA,IAAI,CAAC,KAAO,EAAA;AACV,IAAO,OAAA,KAAA,CAAA;AAAA;AAGT,EAAI,IAAA;AACF,IAAM,MAAA,MAAA,GAAS,IAAI,IAAA,CAAK,KAAK,CAAA;AAC7B,IAAA,MAAA,CAAO,WAAY,EAAA;AACnB,IAAO,OAAA,MAAA;AAAA,GACD,CAAA,MAAA;AACN,IAAO,OAAA,KAAA,CAAA;AAAA;AAEX;AAEO,SAAS,mBAAmB,QAA8B,EAAA;AAC/D,EAAA,OAAO,QAAS,CAAA,IAAA,GACZA,eAAS,CAAA,IAAA,CAAK,KAAM,CAAA,QAAA,CAAS,IAAI,CAAC,CAClC,GAAA,IAAIC,kBAAY,EAAA,CAAE,GAAI,EAAA;AAC5B;AAKO,SAAS,MACd,YAC+B,EAAA;AAC/B,EAAM,MAAA,MAAA,GAAS,aAAa,SAAU,EAAA;AACtC,EAAA,OAAO,IAAIC,kBAAkB,CAAA;AAAA,IAC3B,MAAM,KAAK,UAAY,EAAA;AACrB,MAAA,MAAM,EAAE,KAAO,EAAA,IAAA,EAAS,GAAA,MAAM,OAAO,IAAK,EAAA;AAC1C,MAAA,IAAI,KAAO,EAAA;AACT,QAAA,UAAA,CAAW,QAAQ,KAAK,CAAA;AAAA;AAE1B,MAAA,IAAI,IAAM,EAAA;AACR,QAAA,UAAA,CAAW,KAAM,EAAA;AAAA;AACnB;AACF,GACD,CAAA;AACH;;;;;;"}
|
|
@@ -2,13 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
var errors = require('@backstage/errors');
|
|
4
4
|
var jose = require('jose');
|
|
5
|
-
var fetch = require('node-fetch');
|
|
6
5
|
var helpers = require('../auth/helpers.cjs.js');
|
|
7
6
|
|
|
8
|
-
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
9
|
-
|
|
10
|
-
var fetch__default = /*#__PURE__*/_interopDefaultCompat(fetch);
|
|
11
|
-
|
|
12
7
|
class DefaultUserInfoService {
|
|
13
8
|
discovery;
|
|
14
9
|
constructor(options) {
|
|
@@ -30,7 +25,7 @@ class DefaultUserInfoService {
|
|
|
30
25
|
}
|
|
31
26
|
let ownershipEntityRefs = tokenEnt;
|
|
32
27
|
if (!ownershipEntityRefs) {
|
|
33
|
-
const userInfoResp = await
|
|
28
|
+
const userInfoResp = await fetch(
|
|
34
29
|
`${await this.discovery.getBaseUrl("auth")}/v1/userinfo`,
|
|
35
30
|
{
|
|
36
31
|
headers: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DefaultUserInfoService.cjs.js","sources":["../../../src/entrypoints/userInfo/DefaultUserInfoService.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 UserInfoService,\n BackstageUserInfo,\n DiscoveryService,\n BackstageCredentials,\n} from '@backstage/backend-plugin-api';\nimport { ResponseError } from '@backstage/errors';\nimport { decodeJwt } from 'jose';\nimport
|
|
1
|
+
{"version":3,"file":"DefaultUserInfoService.cjs.js","sources":["../../../src/entrypoints/userInfo/DefaultUserInfoService.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 UserInfoService,\n BackstageUserInfo,\n DiscoveryService,\n BackstageCredentials,\n} from '@backstage/backend-plugin-api';\nimport { ResponseError } from '@backstage/errors';\nimport { decodeJwt } from 'jose';\nimport { toInternalBackstageCredentials } from '../auth/helpers';\n\nexport type Options = {\n discovery: DiscoveryService;\n};\n\nexport class DefaultUserInfoService implements UserInfoService {\n private readonly discovery: DiscoveryService;\n\n constructor(options: Options) {\n this.discovery = options.discovery;\n }\n\n async getUserInfo(\n credentials: BackstageCredentials,\n ): Promise<BackstageUserInfo> {\n const internalCredentials = toInternalBackstageCredentials(credentials);\n if (internalCredentials.principal.type !== 'user') {\n throw new Error('Only user credentials are supported');\n }\n if (!internalCredentials.token) {\n throw new Error('User credentials is unexpectedly missing token');\n }\n const { sub: userEntityRef, ent: tokenEnt } = decodeJwt(\n internalCredentials.token,\n );\n\n if (typeof userEntityRef !== 'string') {\n throw new Error('User entity ref must be a string');\n }\n\n let ownershipEntityRefs = tokenEnt;\n\n if (!ownershipEntityRefs) {\n const userInfoResp = await fetch(\n `${await this.discovery.getBaseUrl('auth')}/v1/userinfo`,\n {\n headers: {\n Authorization: `Bearer ${internalCredentials.token}`,\n },\n },\n );\n\n if (!userInfoResp.ok) {\n throw await ResponseError.fromResponse(userInfoResp);\n }\n\n const {\n claims: { ent },\n } = await userInfoResp.json();\n ownershipEntityRefs = ent;\n }\n\n if (!ownershipEntityRefs) {\n throw new Error('Ownership entity refs can not be determined');\n } else if (\n !Array.isArray(ownershipEntityRefs) ||\n ownershipEntityRefs.some(ref => typeof ref !== 'string')\n ) {\n throw new Error('Ownership entity refs must be an array of strings');\n }\n\n return { userEntityRef, ownershipEntityRefs };\n }\n}\n"],"names":["toInternalBackstageCredentials","decodeJwt","ResponseError"],"mappings":";;;;;;AA8BO,MAAM,sBAAkD,CAAA;AAAA,EAC5C,SAAA;AAAA,EAEjB,YAAY,OAAkB,EAAA;AAC5B,IAAA,IAAA,CAAK,YAAY,OAAQ,CAAA,SAAA;AAAA;AAC3B,EAEA,MAAM,YACJ,WAC4B,EAAA;AAC5B,IAAM,MAAA,mBAAA,GAAsBA,uCAA+B,WAAW,CAAA;AACtE,IAAI,IAAA,mBAAA,CAAoB,SAAU,CAAA,IAAA,KAAS,MAAQ,EAAA;AACjD,MAAM,MAAA,IAAI,MAAM,qCAAqC,CAAA;AAAA;AAEvD,IAAI,IAAA,CAAC,oBAAoB,KAAO,EAAA;AAC9B,MAAM,MAAA,IAAI,MAAM,gDAAgD,CAAA;AAAA;AAElE,IAAA,MAAM,EAAE,GAAA,EAAK,aAAe,EAAA,GAAA,EAAK,UAAa,GAAAC,cAAA;AAAA,MAC5C,mBAAoB,CAAA;AAAA,KACtB;AAEA,IAAI,IAAA,OAAO,kBAAkB,QAAU,EAAA;AACrC,MAAM,MAAA,IAAI,MAAM,kCAAkC,CAAA;AAAA;AAGpD,IAAA,IAAI,mBAAsB,GAAA,QAAA;AAE1B,IAAA,IAAI,CAAC,mBAAqB,EAAA;AACxB,MAAA,MAAM,eAAe,MAAM,KAAA;AAAA,QACzB,GAAG,MAAM,IAAA,CAAK,SAAU,CAAA,UAAA,CAAW,MAAM,CAAC,CAAA,YAAA,CAAA;AAAA,QAC1C;AAAA,UACE,OAAS,EAAA;AAAA,YACP,aAAA,EAAe,CAAU,OAAA,EAAA,mBAAA,CAAoB,KAAK,CAAA;AAAA;AACpD;AACF,OACF;AAEA,MAAI,IAAA,CAAC,aAAa,EAAI,EAAA;AACpB,QAAM,MAAA,MAAMC,oBAAc,CAAA,YAAA,CAAa,YAAY,CAAA;AAAA;AAGrD,MAAM,MAAA;AAAA,QACJ,MAAA,EAAQ,EAAE,GAAI;AAAA,OAChB,GAAI,MAAM,YAAA,CAAa,IAAK,EAAA;AAC5B,MAAsB,mBAAA,GAAA,GAAA;AAAA;AAGxB,IAAA,IAAI,CAAC,mBAAqB,EAAA;AACxB,MAAM,MAAA,IAAI,MAAM,6CAA6C,CAAA;AAAA,KAE7D,MAAA,IAAA,CAAC,KAAM,CAAA,OAAA,CAAQ,mBAAmB,CAAA,IAClC,mBAAoB,CAAA,IAAA,CAAK,CAAO,GAAA,KAAA,OAAO,GAAQ,KAAA,QAAQ,CACvD,EAAA;AACA,MAAM,MAAA,IAAI,MAAM,mDAAmD,CAAA;AAAA;AAGrE,IAAO,OAAA,EAAE,eAAe,mBAAoB,EAAA;AAAA;AAEhD;;;;"}
|