@backstage/backend-defaults 0.6.0-next.0 → 0.6.0-next.1
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 +24 -0
- package/config.d.ts +34 -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/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 +5 -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 +14 -1
- package/dist/package.json.cjs.js.map +1 -1
- package/dist/urlReader.d.ts +17 -2
- package/package.json +19 -10
|
@@ -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;;;;"}
|
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.6.0-next.
|
|
6
|
+
var version = "0.6.0-next.1";
|
|
7
7
|
var description = "Backend defaults used by Backstage backend apps";
|
|
8
8
|
var backstage = {
|
|
9
9
|
role: "node-library"
|
|
@@ -188,11 +188,20 @@ var dependencies = {
|
|
|
188
188
|
yn: "^4.0.0",
|
|
189
189
|
zod: "^3.22.4"
|
|
190
190
|
};
|
|
191
|
+
var peerDependencies = {
|
|
192
|
+
"@google-cloud/cloud-sql-connector": "^1.4.0"
|
|
193
|
+
};
|
|
194
|
+
var peerDependenciesMeta = {
|
|
195
|
+
"@google-cloud/cloud-sql-connector": {
|
|
196
|
+
optional: true
|
|
197
|
+
}
|
|
198
|
+
};
|
|
191
199
|
var devDependencies = {
|
|
192
200
|
"@aws-sdk/util-stream-node": "^3.350.0",
|
|
193
201
|
"@backstage/backend-plugin-api": "workspace:^",
|
|
194
202
|
"@backstage/backend-test-utils": "workspace:^",
|
|
195
203
|
"@backstage/cli": "workspace:^",
|
|
204
|
+
"@google-cloud/cloud-sql-connector": "^1.4.0",
|
|
196
205
|
"@types/archiver": "^6.0.0",
|
|
197
206
|
"@types/base64-stream": "^1.0.2",
|
|
198
207
|
"@types/concat-stream": "^2.0.0",
|
|
@@ -226,6 +235,8 @@ var packageinfo = {
|
|
|
226
235
|
files: files,
|
|
227
236
|
scripts: scripts,
|
|
228
237
|
dependencies: dependencies,
|
|
238
|
+
peerDependencies: peerDependencies,
|
|
239
|
+
peerDependenciesMeta: peerDependenciesMeta,
|
|
229
240
|
devDependencies: devDependencies,
|
|
230
241
|
configSchema: configSchema
|
|
231
242
|
};
|
|
@@ -243,6 +254,8 @@ exports.keywords = keywords;
|
|
|
243
254
|
exports.license = license;
|
|
244
255
|
exports.main = main;
|
|
245
256
|
exports.name = name;
|
|
257
|
+
exports.peerDependencies = peerDependencies;
|
|
258
|
+
exports.peerDependenciesMeta = peerDependenciesMeta;
|
|
246
259
|
exports.publishConfig = publishConfig;
|
|
247
260
|
exports.repository = repository;
|
|
248
261
|
exports.scripts = scripts;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"package.json.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"package.json.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/urlReader.d.ts
CHANGED
|
@@ -47,6 +47,17 @@ type ReadTreeResponseFactoryOptions = {
|
|
|
47
47
|
filter?: (path: string, info?: {
|
|
48
48
|
size: number;
|
|
49
49
|
}) => boolean;
|
|
50
|
+
} | {
|
|
51
|
+
/** A response from a fetch request */
|
|
52
|
+
response: Response;
|
|
53
|
+
/** If unset, the files at the root of the tree will be read. Subpath must not contain the name of the top level directory. */
|
|
54
|
+
subpath?: string;
|
|
55
|
+
/** etag of the blob, to optionally override what the response header may or may not say */
|
|
56
|
+
etag?: string;
|
|
57
|
+
/** Filter passed on from the ReadTreeOptions */
|
|
58
|
+
filter?: (path: string, info?: {
|
|
59
|
+
size: number;
|
|
60
|
+
}) => boolean;
|
|
50
61
|
};
|
|
51
62
|
/**
|
|
52
63
|
* Options that control {@link ReadTreeResponseFactory.fromReadableArray}
|
|
@@ -389,13 +400,17 @@ declare class FetchUrlReader implements UrlReaderService {
|
|
|
389
400
|
*/
|
|
390
401
|
declare class ReadUrlResponseFactory {
|
|
391
402
|
/**
|
|
392
|
-
* Resolves a
|
|
403
|
+
* Resolves a UrlReaderServiceReadUrlResponse from a Readable stream.
|
|
393
404
|
*/
|
|
394
405
|
static fromReadable(stream: Readable, options?: ReadUrlResponseFactoryFromStreamOptions): Promise<UrlReaderServiceReadUrlResponse>;
|
|
395
406
|
/**
|
|
396
|
-
* Resolves a
|
|
407
|
+
* Resolves a UrlReaderServiceReadUrlResponse from an old-style NodeJS.ReadableStream.
|
|
397
408
|
*/
|
|
398
409
|
static fromNodeJSReadable(oldStyleStream: NodeJS.ReadableStream, options?: ReadUrlResponseFactoryFromStreamOptions): Promise<UrlReaderServiceReadUrlResponse>;
|
|
410
|
+
/**
|
|
411
|
+
* Resolves a UrlReaderServiceReadUrlResponse from a native fetch response body.
|
|
412
|
+
*/
|
|
413
|
+
static fromResponse(response: Response): Promise<UrlReaderServiceReadUrlResponse>;
|
|
399
414
|
}
|
|
400
415
|
|
|
401
416
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/backend-defaults",
|
|
3
|
-
"version": "0.6.0-next.
|
|
3
|
+
"version": "0.6.0-next.1",
|
|
4
4
|
"description": "Backend defaults used by Backstage backend apps",
|
|
5
5
|
"backstage": {
|
|
6
6
|
"role": "node-library"
|
|
@@ -193,19 +193,19 @@
|
|
|
193
193
|
"@aws-sdk/types": "^3.347.0",
|
|
194
194
|
"@azure/identity": "^4.0.0",
|
|
195
195
|
"@azure/storage-blob": "^12.5.0",
|
|
196
|
-
"@backstage/backend-app-api": "1.0
|
|
196
|
+
"@backstage/backend-app-api": "1.1.0-next.1",
|
|
197
197
|
"@backstage/backend-dev-utils": "0.1.5",
|
|
198
|
-
"@backstage/backend-plugin-api": "1.0
|
|
198
|
+
"@backstage/backend-plugin-api": "1.1.0-next.1",
|
|
199
199
|
"@backstage/cli-common": "0.1.15",
|
|
200
200
|
"@backstage/cli-node": "0.2.11-next.0",
|
|
201
201
|
"@backstage/config": "1.3.0",
|
|
202
|
-
"@backstage/config-loader": "1.9.
|
|
202
|
+
"@backstage/config-loader": "1.9.3-next.0",
|
|
203
203
|
"@backstage/errors": "1.2.5",
|
|
204
204
|
"@backstage/integration": "1.16.0-next.0",
|
|
205
205
|
"@backstage/integration-aws-node": "0.1.13",
|
|
206
|
-
"@backstage/plugin-auth-node": "0.5.5-next.
|
|
207
|
-
"@backstage/plugin-events-node": "0.4.6-next.
|
|
208
|
-
"@backstage/plugin-permission-node": "0.8.6-next.
|
|
206
|
+
"@backstage/plugin-auth-node": "0.5.5-next.1",
|
|
207
|
+
"@backstage/plugin-events-node": "0.4.6-next.1",
|
|
208
|
+
"@backstage/plugin-permission-node": "0.8.6-next.1",
|
|
209
209
|
"@backstage/types": "1.2.0",
|
|
210
210
|
"@google-cloud/storage": "^7.0.0",
|
|
211
211
|
"@keyv/memcache": "^2.0.1",
|
|
@@ -257,11 +257,20 @@
|
|
|
257
257
|
"yn": "^4.0.0",
|
|
258
258
|
"zod": "^3.22.4"
|
|
259
259
|
},
|
|
260
|
+
"peerDependencies": {
|
|
261
|
+
"@google-cloud/cloud-sql-connector": "^1.4.0"
|
|
262
|
+
},
|
|
263
|
+
"peerDependenciesMeta": {
|
|
264
|
+
"@google-cloud/cloud-sql-connector": {
|
|
265
|
+
"optional": true
|
|
266
|
+
}
|
|
267
|
+
},
|
|
260
268
|
"devDependencies": {
|
|
261
269
|
"@aws-sdk/util-stream-node": "^3.350.0",
|
|
262
|
-
"@backstage/backend-plugin-api": "1.0
|
|
263
|
-
"@backstage/backend-test-utils": "1.2.0-next.
|
|
264
|
-
"@backstage/cli": "0.29.3-next.
|
|
270
|
+
"@backstage/backend-plugin-api": "1.1.0-next.1",
|
|
271
|
+
"@backstage/backend-test-utils": "1.2.0-next.1",
|
|
272
|
+
"@backstage/cli": "0.29.3-next.1",
|
|
273
|
+
"@google-cloud/cloud-sql-connector": "^1.4.0",
|
|
265
274
|
"@types/archiver": "^6.0.0",
|
|
266
275
|
"@types/base64-stream": "^1.0.2",
|
|
267
276
|
"@types/concat-stream": "^2.0.0",
|