@backstage/backend-defaults 0.5.1-next.1 → 0.5.1-next.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/auth/package.json +1 -1
- package/cache/package.json +1 -1
- package/database/package.json +1 -1
- package/discovery/package.json +1 -1
- package/dist/CreateBackend.cjs.js +49 -0
- package/dist/CreateBackend.cjs.js.map +1 -0
- package/dist/PackageDiscoveryService.cjs.js +109 -0
- package/dist/PackageDiscoveryService.cjs.js.map +1 -0
- package/dist/auth.cjs.js +2 -996
- package/dist/auth.cjs.js.map +1 -1
- package/dist/cache.cjs.js +4 -204
- package/dist/cache.cjs.js.map +1 -1
- package/dist/database.cjs.js +4 -957
- package/dist/database.cjs.js.map +1 -1
- package/dist/database.d.ts +4 -1
- package/dist/discovery.cjs.js +4 -92
- package/dist/discovery.cjs.js.map +1 -1
- package/dist/discoveryFeatureLoader.cjs.js +19 -0
- package/dist/discoveryFeatureLoader.cjs.js.map +1 -0
- package/dist/entrypoints/auth/DefaultAuthService.cjs.js +130 -0
- package/dist/entrypoints/auth/DefaultAuthService.cjs.js.map +1 -0
- package/dist/entrypoints/auth/JwksClient.cjs.js +49 -0
- package/dist/entrypoints/auth/JwksClient.cjs.js.map +1 -0
- package/dist/entrypoints/auth/authServiceFactory.cjs.js +57 -0
- package/dist/entrypoints/auth/authServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/auth/external/ExternalTokenHandler.cjs.js +78 -0
- package/dist/entrypoints/auth/external/ExternalTokenHandler.cjs.js.map +1 -0
- package/dist/entrypoints/auth/external/helpers.cjs.js +92 -0
- package/dist/entrypoints/auth/external/helpers.cjs.js.map +1 -0
- package/dist/entrypoints/auth/external/jwks.cjs.js +63 -0
- package/dist/entrypoints/auth/external/jwks.cjs.js.map +1 -0
- package/dist/entrypoints/auth/external/legacy.cjs.js +73 -0
- package/dist/entrypoints/auth/external/legacy.cjs.js.map +1 -0
- package/dist/entrypoints/auth/external/static.cjs.js +33 -0
- package/dist/entrypoints/auth/external/static.cjs.js.map +1 -0
- package/dist/{cjs/helpers-D2f1CG0o.cjs.js → entrypoints/auth/helpers.cjs.js} +1 -1
- package/dist/entrypoints/auth/helpers.cjs.js.map +1 -0
- package/dist/entrypoints/auth/plugin/PluginTokenHandler.cjs.js +147 -0
- package/dist/entrypoints/auth/plugin/PluginTokenHandler.cjs.js.map +1 -0
- package/dist/entrypoints/auth/plugin/keys/DatabaseKeyStore.cjs.js +73 -0
- package/dist/entrypoints/auth/plugin/keys/DatabaseKeyStore.cjs.js.map +1 -0
- package/dist/entrypoints/auth/plugin/keys/DatabasePluginKeySource.cjs.js +75 -0
- package/dist/entrypoints/auth/plugin/keys/DatabasePluginKeySource.cjs.js.map +1 -0
- package/dist/entrypoints/auth/plugin/keys/StaticConfigPluginKeySource.cjs.js +91 -0
- package/dist/entrypoints/auth/plugin/keys/StaticConfigPluginKeySource.cjs.js.map +1 -0
- package/dist/entrypoints/auth/plugin/keys/createPluginKeySource.cjs.js +29 -0
- package/dist/entrypoints/auth/plugin/keys/createPluginKeySource.cjs.js.map +1 -0
- package/dist/entrypoints/auth/user/UserTokenHandler.cjs.js +110 -0
- package/dist/entrypoints/auth/user/UserTokenHandler.cjs.js.map +1 -0
- package/dist/entrypoints/cache/CacheClient.cjs.js +50 -0
- package/dist/entrypoints/cache/CacheClient.cjs.js.map +1 -0
- package/dist/entrypoints/cache/CacheManager.cjs.js +147 -0
- package/dist/entrypoints/cache/CacheManager.cjs.js.map +1 -0
- package/dist/entrypoints/cache/cacheServiceFactory.cjs.js +22 -0
- package/dist/entrypoints/cache/cacheServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/cache/types.cjs.js +10 -0
- package/dist/entrypoints/cache/types.cjs.js.map +1 -0
- package/dist/entrypoints/database/DatabaseManager.cjs.js +173 -0
- package/dist/entrypoints/database/DatabaseManager.cjs.js.map +1 -0
- package/dist/entrypoints/database/connectors/defaultNameOverride.cjs.js +14 -0
- package/dist/entrypoints/database/connectors/defaultNameOverride.cjs.js.map +1 -0
- package/dist/entrypoints/database/connectors/defaultSchemaOverride.cjs.js +12 -0
- package/dist/entrypoints/database/connectors/defaultSchemaOverride.cjs.js.map +1 -0
- package/dist/entrypoints/database/connectors/mergeDatabaseConfig.cjs.js +10 -0
- package/dist/entrypoints/database/connectors/mergeDatabaseConfig.cjs.js.map +1 -0
- package/dist/entrypoints/database/connectors/mysql.cjs.js +278 -0
- package/dist/entrypoints/database/connectors/mysql.cjs.js.map +1 -0
- package/dist/entrypoints/database/connectors/postgres.cjs.js +304 -0
- package/dist/entrypoints/database/connectors/postgres.cjs.js.map +1 -0
- package/dist/entrypoints/database/connectors/sqlite3.cjs.js +251 -0
- package/dist/entrypoints/database/connectors/sqlite3.cjs.js.map +1 -0
- package/dist/entrypoints/database/databaseServiceFactory.cjs.js +36 -0
- package/dist/entrypoints/database/databaseServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/discovery/HostDiscovery.cjs.js +86 -0
- package/dist/entrypoints/discovery/HostDiscovery.cjs.js.map +1 -0
- package/dist/entrypoints/discovery/discoveryServiceFactory.cjs.js +17 -0
- package/dist/entrypoints/discovery/discoveryServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/httpAuth/httpAuthServiceFactory.cjs.js +192 -0
- package/dist/entrypoints/httpAuth/httpAuthServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/httpRouter/createAuthIntegrationRouter.cjs.js +19 -0
- package/dist/entrypoints/httpRouter/createAuthIntegrationRouter.cjs.js.map +1 -0
- package/dist/entrypoints/httpRouter/createCookieAuthRefreshMiddleware.cjs.js +26 -0
- package/dist/entrypoints/httpRouter/createCookieAuthRefreshMiddleware.cjs.js.map +1 -0
- package/dist/entrypoints/httpRouter/createCredentialsBarrier.cjs.js +63 -0
- package/dist/entrypoints/httpRouter/createCredentialsBarrier.cjs.js.map +1 -0
- package/dist/entrypoints/httpRouter/createLifecycleMiddleware.cjs.js +52 -0
- package/dist/entrypoints/httpRouter/createLifecycleMiddleware.cjs.js.map +1 -0
- package/dist/entrypoints/httpRouter/httpRouterServiceFactory.cjs.js +48 -0
- package/dist/entrypoints/httpRouter/httpRouterServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/lifecycle/lifecycleServiceFactory.cjs.js +88 -0
- package/dist/entrypoints/lifecycle/lifecycleServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/logger/loggerServiceFactory.cjs.js +17 -0
- package/dist/entrypoints/logger/loggerServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/permissions/permissionsServiceFactory.cjs.js +22 -0
- package/dist/entrypoints/permissions/permissionsServiceFactory.cjs.js.map +1 -0
- package/dist/{cjs/createConfigSecretEnumerator-DShyoWWL.cjs.js → entrypoints/rootConfig/createConfigSecretEnumerator.cjs.js} +1 -1
- package/dist/entrypoints/rootConfig/createConfigSecretEnumerator.cjs.js.map +1 -0
- package/dist/entrypoints/rootConfig/rootConfigServiceFactory.cjs.js +26 -0
- package/dist/entrypoints/rootConfig/rootConfigServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/rootHealth/rootHealthServiceFactory.cjs.js +41 -0
- package/dist/entrypoints/rootHealth/rootHealthServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/rootHttpRouter/DefaultRootHttpRouter.cjs.js +77 -0
- package/dist/entrypoints/rootHttpRouter/DefaultRootHttpRouter.cjs.js.map +1 -0
- package/dist/entrypoints/rootHttpRouter/createHealthRouter.cjs.js +29 -0
- package/dist/entrypoints/rootHttpRouter/createHealthRouter.cjs.js.map +1 -0
- package/dist/entrypoints/rootHttpRouter/http/MiddlewareFactory.cjs.js +187 -0
- package/dist/entrypoints/rootHttpRouter/http/MiddlewareFactory.cjs.js.map +1 -0
- package/dist/entrypoints/rootHttpRouter/http/applyInternalErrorFilter.cjs.js +28 -0
- package/dist/entrypoints/rootHttpRouter/http/applyInternalErrorFilter.cjs.js.map +1 -0
- package/dist/{cjs/config-BDOwXIyo.cjs.js → entrypoints/rootHttpRouter/http/config.cjs.js} +1 -1
- package/dist/entrypoints/rootHttpRouter/http/config.cjs.js.map +1 -0
- package/dist/entrypoints/rootHttpRouter/http/createHttpServer.cjs.js +88 -0
- package/dist/entrypoints/rootHttpRouter/http/createHttpServer.cjs.js.map +1 -0
- package/dist/entrypoints/rootHttpRouter/http/getGeneratedCertificate.cjs.js +130 -0
- package/dist/entrypoints/rootHttpRouter/http/getGeneratedCertificate.cjs.js.map +1 -0
- package/dist/entrypoints/rootHttpRouter/http/readCorsOptions.cjs.js +51 -0
- package/dist/entrypoints/rootHttpRouter/http/readCorsOptions.cjs.js.map +1 -0
- package/dist/entrypoints/rootHttpRouter/http/readHelmetOptions.cjs.js +62 -0
- package/dist/entrypoints/rootHttpRouter/http/readHelmetOptions.cjs.js.map +1 -0
- package/dist/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.cjs.js +73 -0
- package/dist/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/rootLifecycle/rootLifecycleServiceFactory.cjs.js +76 -0
- package/dist/entrypoints/rootLifecycle/rootLifecycleServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/rootLogger/WinstonLogger.cjs.js +114 -0
- package/dist/entrypoints/rootLogger/WinstonLogger.cjs.js.map +1 -0
- package/dist/entrypoints/rootLogger/rootLoggerServiceFactory.cjs.js +30 -0
- package/dist/entrypoints/rootLogger/rootLoggerServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/scheduler/database/migrateBackendTasks.cjs.js +18 -0
- package/dist/entrypoints/scheduler/database/migrateBackendTasks.cjs.js.map +1 -0
- package/dist/entrypoints/scheduler/database/tables.cjs.js +8 -0
- package/dist/entrypoints/scheduler/database/tables.cjs.js.map +1 -0
- package/dist/entrypoints/scheduler/lib/DefaultSchedulerService.cjs.js +37 -0
- package/dist/entrypoints/scheduler/lib/DefaultSchedulerService.cjs.js.map +1 -0
- package/dist/entrypoints/scheduler/lib/LocalTaskWorker.cjs.js +105 -0
- package/dist/entrypoints/scheduler/lib/LocalTaskWorker.cjs.js.map +1 -0
- package/dist/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.cjs.js +138 -0
- package/dist/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.cjs.js.map +1 -0
- package/dist/entrypoints/scheduler/lib/PluginTaskSchedulerJanitor.cjs.js +59 -0
- package/dist/entrypoints/scheduler/lib/PluginTaskSchedulerJanitor.cjs.js.map +1 -0
- package/dist/entrypoints/scheduler/lib/TaskWorker.cjs.js +275 -0
- package/dist/entrypoints/scheduler/lib/TaskWorker.cjs.js.map +1 -0
- package/dist/entrypoints/scheduler/lib/types.cjs.js +60 -0
- package/dist/entrypoints/scheduler/lib/types.cjs.js.map +1 -0
- package/dist/entrypoints/scheduler/lib/util.cjs.js +66 -0
- package/dist/entrypoints/scheduler/lib/util.cjs.js.map +1 -0
- package/dist/entrypoints/scheduler/schedulerServiceFactory.cjs.js +19 -0
- package/dist/entrypoints/scheduler/schedulerServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/AwsCodeCommitUrlReader.cjs.js +274 -0
- package/dist/entrypoints/urlReader/lib/AwsCodeCommitUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/AwsS3UrlReader.cjs.js +261 -0
- package/dist/entrypoints/urlReader/lib/AwsS3UrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/AzureUrlReader.cjs.js +148 -0
- package/dist/entrypoints/urlReader/lib/AzureUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/BitbucketCloudUrlReader.cjs.js +174 -0
- package/dist/entrypoints/urlReader/lib/BitbucketCloudUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/BitbucketServerUrlReader.cjs.js +170 -0
- package/dist/entrypoints/urlReader/lib/BitbucketServerUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/BitbucketUrlReader.cjs.js +182 -0
- package/dist/entrypoints/urlReader/lib/BitbucketUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/FetchUrlReader.cjs.js +132 -0
- package/dist/entrypoints/urlReader/lib/FetchUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/GerritUrlReader.cjs.js +147 -0
- package/dist/entrypoints/urlReader/lib/GerritUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/GiteaUrlReader.cjs.js +122 -0
- package/dist/entrypoints/urlReader/lib/GiteaUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/GithubUrlReader.cjs.js +226 -0
- package/dist/entrypoints/urlReader/lib/GithubUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/GitlabUrlReader.cjs.js +277 -0
- package/dist/entrypoints/urlReader/lib/GitlabUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/GoogleGcsUrlReader.cjs.js +129 -0
- package/dist/entrypoints/urlReader/lib/GoogleGcsUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/HarnessUrlReader.cjs.js +120 -0
- package/dist/entrypoints/urlReader/lib/HarnessUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/ReadUrlResponseFactory.cjs.js +49 -0
- package/dist/entrypoints/urlReader/lib/ReadUrlResponseFactory.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/UrlReaderPredicateMux.cjs.js +46 -0
- package/dist/entrypoints/urlReader/lib/UrlReaderPredicateMux.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/UrlReaders.cjs.js +68 -0
- package/dist/entrypoints/urlReader/lib/UrlReaders.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/tree/ReadTreeResponseFactory.cjs.js +46 -0
- package/dist/entrypoints/urlReader/lib/tree/ReadTreeResponseFactory.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/tree/ReadableArrayResponse.cjs.js +78 -0
- package/dist/entrypoints/urlReader/lib/tree/ReadableArrayResponse.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/tree/TarArchiveResponse.cjs.js +147 -0
- package/dist/entrypoints/urlReader/lib/tree/TarArchiveResponse.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/tree/ZipArchiveResponse.cjs.js +161 -0
- package/dist/entrypoints/urlReader/lib/tree/ZipArchiveResponse.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/tree/util.cjs.js +28 -0
- package/dist/entrypoints/urlReader/lib/tree/util.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/util.cjs.js +11 -0
- package/dist/entrypoints/urlReader/lib/util.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/urlReaderServiceFactory.cjs.js +29 -0
- package/dist/entrypoints/urlReader/urlReaderServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/userInfo/DefaultUserInfoService.cjs.js +59 -0
- package/dist/entrypoints/userInfo/DefaultUserInfoService.cjs.js.map +1 -0
- package/dist/entrypoints/userInfo/userInfoServiceFactory.cjs.js +17 -0
- package/dist/entrypoints/userInfo/userInfoServiceFactory.cjs.js.map +1 -0
- package/dist/httpAuth.cjs.js +3 -187
- package/dist/httpAuth.cjs.js.map +1 -1
- package/dist/httpRouter.cjs.js +2 -166
- package/dist/httpRouter.cjs.js.map +1 -1
- package/dist/index.cjs.js +4 -160
- package/dist/index.cjs.js.map +1 -1
- package/dist/lib/escapeRegExp.cjs.js +8 -0
- package/dist/lib/escapeRegExp.cjs.js.map +1 -0
- package/dist/lifecycle.cjs.js +3 -58
- package/dist/lifecycle.cjs.js.map +1 -1
- package/dist/logger.cjs.js +3 -12
- package/dist/logger.cjs.js.map +1 -1
- package/dist/package.json.cjs.js +252 -0
- package/dist/package.json.cjs.js.map +1 -0
- package/dist/permissions.cjs.js +3 -17
- package/dist/permissions.cjs.js.map +1 -1
- package/dist/rootConfig.cjs.js +4 -22
- package/dist/rootConfig.cjs.js.map +1 -1
- package/dist/rootHealth.cjs.js +3 -35
- package/dist/rootHealth.cjs.js.map +1 -1
- package/dist/rootHttpRouter.cjs.js +15 -651
- package/dist/rootHttpRouter.cjs.js.map +1 -1
- package/dist/rootLifecycle.cjs.js +3 -70
- package/dist/rootLifecycle.cjs.js.map +1 -1
- package/dist/rootLogger.cjs.js +4 -137
- package/dist/rootLogger.cjs.js.map +1 -1
- package/dist/scheduler.cjs.js +4 -693
- package/dist/scheduler.cjs.js.map +1 -1
- package/dist/scheduler.d.ts +2 -1
- package/dist/urlReader.cjs.js +32 -2962
- package/dist/urlReader.cjs.js.map +1 -1
- package/dist/userInfo.cjs.js +2 -64
- package/dist/userInfo.cjs.js.map +1 -1
- package/httpAuth/package.json +1 -1
- package/httpRouter/package.json +1 -1
- package/lifecycle/package.json +1 -1
- package/logger/package.json +1 -1
- package/package.json +13 -13
- package/permissions/package.json +1 -1
- package/rootConfig/package.json +1 -1
- package/rootHealth/package.json +1 -1
- package/rootHttpRouter/package.json +1 -1
- package/rootLifecycle/package.json +1 -1
- package/rootLogger/package.json +1 -1
- package/scheduler/package.json +1 -1
- package/urlReader/package.json +1 -1
- package/userInfo/package.json +1 -1
- package/dist/cjs/config-BDOwXIyo.cjs.js.map +0 -1
- package/dist/cjs/createConfigSecretEnumerator-DShyoWWL.cjs.js.map +0 -1
- package/dist/cjs/helpers-D2f1CG0o.cjs.js.map +0 -1
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var integrationAwsNode = require('@backstage/integration-aws-node');
|
|
4
|
+
var integration = require('@backstage/integration');
|
|
5
|
+
var errors = require('@backstage/errors');
|
|
6
|
+
var credentialProviders = require('@aws-sdk/credential-providers');
|
|
7
|
+
var clientCodecommit = require('@aws-sdk/client-codecommit');
|
|
8
|
+
var stream = require('stream');
|
|
9
|
+
var ReadUrlResponseFactory = require('./ReadUrlResponseFactory.cjs.js');
|
|
10
|
+
var posix = require('path/posix');
|
|
11
|
+
var abortController = require('@aws-sdk/abort-controller');
|
|
12
|
+
|
|
13
|
+
function parseUrl(url, requireGitPath = false) {
|
|
14
|
+
const parsedUrl = new URL(url);
|
|
15
|
+
if (parsedUrl.pathname.includes("/files/edit/")) {
|
|
16
|
+
throw new Error(
|
|
17
|
+
"Please provide the view url to yaml file from CodeCommit, not the edit url"
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
if (requireGitPath && !parsedUrl.pathname.includes("/browse/")) {
|
|
21
|
+
throw new Error("Please provide full path to yaml file from CodeCommit");
|
|
22
|
+
}
|
|
23
|
+
const hostMatch = parsedUrl.host.match(
|
|
24
|
+
/^([^\.]+)\.console\.aws\.amazon\.com$/
|
|
25
|
+
);
|
|
26
|
+
if (!hostMatch) {
|
|
27
|
+
throw new Error(
|
|
28
|
+
`Invalid AWS CodeCommit URL (unexpected host format): ${url}`
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
const [, region] = hostMatch;
|
|
32
|
+
const pathMatch = parsedUrl.pathname.match(
|
|
33
|
+
/^\/codesuite\/codecommit\/repositories\/([^\/]+)\/browse\/((.*)\/)?--\/(.*)$/
|
|
34
|
+
);
|
|
35
|
+
if (!pathMatch) {
|
|
36
|
+
if (!requireGitPath) {
|
|
37
|
+
const pathname = parsedUrl.pathname.split("/--/")[0].replace("/codesuite/codecommit/repositories/", "");
|
|
38
|
+
const [repositoryName2, commitSpecifier2] = pathname.split("/browse");
|
|
39
|
+
return {
|
|
40
|
+
region,
|
|
41
|
+
repositoryName: repositoryName2.replace(/^\/|\/$/g, ""),
|
|
42
|
+
path: "/",
|
|
43
|
+
commitSpecifier: commitSpecifier2 === "" ? void 0 : commitSpecifier2?.replace(/^\/|\/$/g, "")
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
throw new Error(
|
|
47
|
+
`Invalid AWS CodeCommit URL (unexpected path format): ${url}`
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
const [, repositoryName, , commitSpecifier, path] = pathMatch;
|
|
51
|
+
return {
|
|
52
|
+
region,
|
|
53
|
+
repositoryName,
|
|
54
|
+
path,
|
|
55
|
+
// the commitSpecifier is passed to AWS SDK which does not allow empty strings so replace empty string with undefined
|
|
56
|
+
commitSpecifier: commitSpecifier === "" ? void 0 : commitSpecifier
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
class AwsCodeCommitUrlReader {
|
|
60
|
+
constructor(credsManager, integration, deps) {
|
|
61
|
+
this.credsManager = credsManager;
|
|
62
|
+
this.integration = integration;
|
|
63
|
+
this.deps = deps;
|
|
64
|
+
}
|
|
65
|
+
static factory = ({ config, treeResponseFactory }) => {
|
|
66
|
+
const integrations = integration.ScmIntegrations.fromConfig(config);
|
|
67
|
+
const credsManager = integrationAwsNode.DefaultAwsCredentialsManager.fromConfig(config);
|
|
68
|
+
return integrations.awsCodeCommit.list().map((integration) => {
|
|
69
|
+
const reader = new AwsCodeCommitUrlReader(credsManager, integration, {
|
|
70
|
+
treeResponseFactory
|
|
71
|
+
});
|
|
72
|
+
const predicate = (url) => {
|
|
73
|
+
return url.host.endsWith(integration.config.host) && url.pathname.startsWith("/codesuite/codecommit");
|
|
74
|
+
};
|
|
75
|
+
return { reader, predicate };
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* If accessKeyId and secretAccessKey are missing, the standard credentials provider chain will be used:
|
|
80
|
+
* https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/DefaultAWSCredentialsProviderChain.html
|
|
81
|
+
*/
|
|
82
|
+
static buildStaticCredentials(accessKeyId, secretAccessKey) {
|
|
83
|
+
return async () => {
|
|
84
|
+
return {
|
|
85
|
+
accessKeyId,
|
|
86
|
+
secretAccessKey
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
static async buildCredentials(credsManager, region, integration) {
|
|
91
|
+
if (!integration) {
|
|
92
|
+
return (await credsManager.getCredentialProvider()).sdkCredentialProvider;
|
|
93
|
+
}
|
|
94
|
+
const accessKeyId = integration.config.accessKeyId;
|
|
95
|
+
const secretAccessKey = integration.config.secretAccessKey;
|
|
96
|
+
let explicitCredentials;
|
|
97
|
+
if (accessKeyId && secretAccessKey) {
|
|
98
|
+
explicitCredentials = AwsCodeCommitUrlReader.buildStaticCredentials(
|
|
99
|
+
accessKeyId,
|
|
100
|
+
secretAccessKey
|
|
101
|
+
);
|
|
102
|
+
} else {
|
|
103
|
+
explicitCredentials = (await credsManager.getCredentialProvider()).sdkCredentialProvider;
|
|
104
|
+
}
|
|
105
|
+
const roleArn = integration.config.roleArn;
|
|
106
|
+
if (roleArn) {
|
|
107
|
+
return credentialProviders.fromTemporaryCredentials({
|
|
108
|
+
masterCredentials: explicitCredentials,
|
|
109
|
+
params: {
|
|
110
|
+
RoleSessionName: "backstage-aws-code-commit-url-reader",
|
|
111
|
+
RoleArn: roleArn,
|
|
112
|
+
ExternalId: integration.config.externalId
|
|
113
|
+
},
|
|
114
|
+
clientConfig: { region }
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
return explicitCredentials;
|
|
118
|
+
}
|
|
119
|
+
async buildCodeCommitClient(credsManager, region, integration) {
|
|
120
|
+
const credentials = await AwsCodeCommitUrlReader.buildCredentials(
|
|
121
|
+
credsManager,
|
|
122
|
+
region,
|
|
123
|
+
integration
|
|
124
|
+
);
|
|
125
|
+
const codeCommit = new clientCodecommit.CodeCommitClient({
|
|
126
|
+
customUserAgent: "backstage-aws-codecommit-url-reader",
|
|
127
|
+
region,
|
|
128
|
+
credentials
|
|
129
|
+
});
|
|
130
|
+
return codeCommit;
|
|
131
|
+
}
|
|
132
|
+
async readUrl(url, options) {
|
|
133
|
+
try {
|
|
134
|
+
const { path, repositoryName, region, commitSpecifier } = parseUrl(
|
|
135
|
+
url,
|
|
136
|
+
true
|
|
137
|
+
);
|
|
138
|
+
const codeCommitClient = await this.buildCodeCommitClient(
|
|
139
|
+
this.credsManager,
|
|
140
|
+
region,
|
|
141
|
+
this.integration
|
|
142
|
+
);
|
|
143
|
+
const abortController$1 = new abortController.AbortController();
|
|
144
|
+
const input = {
|
|
145
|
+
repositoryName,
|
|
146
|
+
commitSpecifier,
|
|
147
|
+
filePath: path
|
|
148
|
+
};
|
|
149
|
+
options?.signal?.addEventListener("abort", () => abortController$1.abort());
|
|
150
|
+
const getObjectCommand = new clientCodecommit.GetFileCommand(input);
|
|
151
|
+
const response = await codeCommitClient.send(
|
|
152
|
+
getObjectCommand,
|
|
153
|
+
{
|
|
154
|
+
abortSignal: abortController$1.signal
|
|
155
|
+
}
|
|
156
|
+
);
|
|
157
|
+
if (options?.etag && options.etag === response.commitId) {
|
|
158
|
+
throw new errors.NotModifiedError();
|
|
159
|
+
}
|
|
160
|
+
return ReadUrlResponseFactory.ReadUrlResponseFactory.fromReadable(
|
|
161
|
+
stream.Readable.from([response?.fileContent]),
|
|
162
|
+
{
|
|
163
|
+
etag: response.commitId
|
|
164
|
+
}
|
|
165
|
+
);
|
|
166
|
+
} catch (e) {
|
|
167
|
+
if (e.$metadata && e.$metadata.httpStatusCode === 304) {
|
|
168
|
+
throw new errors.NotModifiedError();
|
|
169
|
+
}
|
|
170
|
+
if (e.name && e.name === "NotModifiedError") {
|
|
171
|
+
throw new errors.NotModifiedError();
|
|
172
|
+
}
|
|
173
|
+
throw new errors.ForwardedError("Could not retrieve file from CodeCommit", e);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
async readTreePath(codeCommitClient, abortSignal, path, repositoryName, commitSpecifier, etag) {
|
|
177
|
+
const getFolderCommand = new clientCodecommit.GetFolderCommand({
|
|
178
|
+
folderPath: path,
|
|
179
|
+
repositoryName,
|
|
180
|
+
commitSpecifier
|
|
181
|
+
});
|
|
182
|
+
const response = await codeCommitClient.send(getFolderCommand, {
|
|
183
|
+
abortSignal
|
|
184
|
+
});
|
|
185
|
+
if (etag && etag === response.commitId) {
|
|
186
|
+
throw new errors.NotModifiedError();
|
|
187
|
+
}
|
|
188
|
+
const output = [];
|
|
189
|
+
if (response.files) {
|
|
190
|
+
response.files.forEach((file) => {
|
|
191
|
+
if (file.absolutePath) {
|
|
192
|
+
output.push(file.absolutePath);
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
if (!response.subFolders) {
|
|
197
|
+
return output;
|
|
198
|
+
}
|
|
199
|
+
for (const subFolder of response.subFolders) {
|
|
200
|
+
if (subFolder.absolutePath) {
|
|
201
|
+
output.push(
|
|
202
|
+
...await this.readTreePath(
|
|
203
|
+
codeCommitClient,
|
|
204
|
+
abortSignal,
|
|
205
|
+
subFolder.absolutePath,
|
|
206
|
+
repositoryName,
|
|
207
|
+
commitSpecifier,
|
|
208
|
+
etag
|
|
209
|
+
)
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return output;
|
|
214
|
+
}
|
|
215
|
+
async readTree(url, options) {
|
|
216
|
+
try {
|
|
217
|
+
const { path, repositoryName, region, commitSpecifier } = parseUrl(url);
|
|
218
|
+
const codeCommitClient = await this.buildCodeCommitClient(
|
|
219
|
+
this.credsManager,
|
|
220
|
+
region,
|
|
221
|
+
this.integration
|
|
222
|
+
);
|
|
223
|
+
const abortController$1 = new abortController.AbortController();
|
|
224
|
+
options?.signal?.addEventListener("abort", () => abortController$1.abort());
|
|
225
|
+
const allFiles = await this.readTreePath(
|
|
226
|
+
codeCommitClient,
|
|
227
|
+
abortController$1.signal,
|
|
228
|
+
path,
|
|
229
|
+
repositoryName,
|
|
230
|
+
commitSpecifier,
|
|
231
|
+
options?.etag
|
|
232
|
+
);
|
|
233
|
+
const responses = [];
|
|
234
|
+
for (let i = 0; i < allFiles.length; i++) {
|
|
235
|
+
const getFileCommand = new clientCodecommit.GetFileCommand({
|
|
236
|
+
repositoryName,
|
|
237
|
+
filePath: String(allFiles[i]),
|
|
238
|
+
commitSpecifier
|
|
239
|
+
});
|
|
240
|
+
const response = await codeCommitClient.send(getFileCommand);
|
|
241
|
+
const objectData = await stream.Readable.from([response?.fileContent]);
|
|
242
|
+
responses.push({
|
|
243
|
+
data: objectData,
|
|
244
|
+
path: posix.relative(
|
|
245
|
+
path.startsWith("/") ? path : `/${path}`,
|
|
246
|
+
allFiles[i].startsWith("/") ? allFiles[i] : `/${allFiles[i]}`
|
|
247
|
+
)
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
return await this.deps.treeResponseFactory.fromReadableArray(responses);
|
|
251
|
+
} catch (e) {
|
|
252
|
+
if (e.name && e.name === "NotModifiedError") {
|
|
253
|
+
throw new errors.NotModifiedError();
|
|
254
|
+
}
|
|
255
|
+
throw new errors.ForwardedError(
|
|
256
|
+
"Could not retrieve file tree from CodeCommit",
|
|
257
|
+
e
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
async search() {
|
|
262
|
+
throw new Error("AwsCodeCommitReader does not implement search");
|
|
263
|
+
}
|
|
264
|
+
toString() {
|
|
265
|
+
const secretAccessKey = this.integration.config.secretAccessKey;
|
|
266
|
+
return `awsCodeCommit{host=${this.integration.config.host},authed=${Boolean(
|
|
267
|
+
secretAccessKey
|
|
268
|
+
)}}`;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
exports.AwsCodeCommitUrlReader = AwsCodeCommitUrlReader;
|
|
273
|
+
exports.parseUrl = parseUrl;
|
|
274
|
+
//# sourceMappingURL=AwsCodeCommitUrlReader.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AwsCodeCommitUrlReader.cjs.js","sources":["../../../../src/entrypoints/urlReader/lib/AwsCodeCommitUrlReader.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ReaderFactory, ReadTreeResponseFactory } from './types';\nimport {\n UrlReaderService,\n UrlReaderServiceReadTreeOptions,\n UrlReaderServiceReadTreeResponse,\n UrlReaderServiceReadUrlOptions,\n UrlReaderServiceReadUrlResponse,\n UrlReaderServiceSearchResponse,\n} from '@backstage/backend-plugin-api';\nimport {\n AwsCredentialsManager,\n DefaultAwsCredentialsManager,\n} from '@backstage/integration-aws-node';\nimport {\n AwsCodeCommitIntegration,\n ScmIntegrations,\n} from '@backstage/integration';\nimport { ForwardedError, NotModifiedError } from '@backstage/errors';\nimport { fromTemporaryCredentials } from '@aws-sdk/credential-providers';\nimport {\n CodeCommitClient,\n GetFileCommand,\n GetFileCommandInput,\n GetFileCommandOutput,\n GetFolderCommand,\n} from '@aws-sdk/client-codecommit';\nimport { AwsCredentialIdentityProvider } from '@aws-sdk/types';\nimport { Readable } from 'stream';\nimport { ReadUrlResponseFactory } from './ReadUrlResponseFactory';\nimport { relative } from 'path/posix';\nimport { AbortController } from '@aws-sdk/abort-controller';\n\nexport function parseUrl(\n url: string,\n requireGitPath: boolean = false,\n): {\n path: string;\n repositoryName: string;\n region: string;\n commitSpecifier?: string;\n} {\n const parsedUrl = new URL(url);\n\n if (parsedUrl.pathname.includes('/files/edit/')) {\n throw new Error(\n 'Please provide the view url to yaml file from CodeCommit, not the edit url',\n );\n }\n if (requireGitPath && !parsedUrl.pathname.includes('/browse/')) {\n throw new Error('Please provide full path to yaml file from CodeCommit');\n }\n\n const hostMatch = parsedUrl.host.match(\n /^([^\\.]+)\\.console\\.aws\\.amazon\\.com$/,\n );\n if (!hostMatch) {\n throw new Error(\n `Invalid AWS CodeCommit URL (unexpected host format): ${url}`,\n );\n }\n const [, region] = hostMatch;\n\n const pathMatch = parsedUrl.pathname.match(\n /^\\/codesuite\\/codecommit\\/repositories\\/([^\\/]+)\\/browse\\/((.*)\\/)?--\\/(.*)$/,\n );\n\n if (!pathMatch) {\n if (!requireGitPath) {\n const pathname = parsedUrl.pathname\n .split('/--/')[0]\n .replace('/codesuite/codecommit/repositories/', '');\n const [repositoryName, commitSpecifier] = pathname.split('/browse');\n\n return {\n region,\n repositoryName: repositoryName.replace(/^\\/|\\/$/g, ''),\n path: '/',\n commitSpecifier:\n commitSpecifier === ''\n ? undefined\n : commitSpecifier?.replace(/^\\/|\\/$/g, ''),\n };\n }\n throw new Error(\n `Invalid AWS CodeCommit URL (unexpected path format): ${url}`,\n );\n }\n const [, repositoryName, , commitSpecifier, path] = pathMatch;\n\n return {\n region,\n repositoryName,\n path,\n // the commitSpecifier is passed to AWS SDK which does not allow empty strings so replace empty string with undefined\n commitSpecifier: commitSpecifier === '' ? undefined : commitSpecifier,\n };\n}\n\n/**\n * Implements a {@link @backstage/backend-plugin-api#UrlReaderService} for AWS CodeCommit.\n *\n * @public\n */\nexport class AwsCodeCommitUrlReader implements UrlReaderService {\n static factory: ReaderFactory = ({ config, treeResponseFactory }) => {\n const integrations = ScmIntegrations.fromConfig(config);\n const credsManager = DefaultAwsCredentialsManager.fromConfig(config);\n\n return integrations.awsCodeCommit.list().map(integration => {\n const reader = new AwsCodeCommitUrlReader(credsManager, integration, {\n treeResponseFactory,\n });\n const predicate = (url: URL) => {\n return (\n url.host.endsWith(integration.config.host) &&\n url.pathname.startsWith('/codesuite/codecommit')\n );\n };\n\n return { reader, predicate };\n });\n };\n\n constructor(\n private readonly credsManager: AwsCredentialsManager,\n private readonly integration: AwsCodeCommitIntegration,\n private readonly deps: {\n treeResponseFactory: ReadTreeResponseFactory;\n },\n ) {}\n\n /**\n * If accessKeyId and secretAccessKey are missing, the standard credentials provider chain will be used:\n * https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/DefaultAWSCredentialsProviderChain.html\n */\n private static buildStaticCredentials(\n accessKeyId: string,\n secretAccessKey: string,\n ): AwsCredentialIdentityProvider {\n return async () => {\n return {\n accessKeyId,\n secretAccessKey,\n };\n };\n }\n\n private static async buildCredentials(\n credsManager: AwsCredentialsManager,\n region: string,\n integration?: AwsCodeCommitIntegration,\n ): Promise<AwsCredentialIdentityProvider> {\n // Fall back to the default credential chain if neither account ID\n // nor explicit credentials are provided\n if (!integration) {\n return (await credsManager.getCredentialProvider()).sdkCredentialProvider;\n }\n\n const accessKeyId = integration.config.accessKeyId;\n const secretAccessKey = integration.config.secretAccessKey;\n let explicitCredentials: AwsCredentialIdentityProvider;\n if (accessKeyId && secretAccessKey) {\n explicitCredentials = AwsCodeCommitUrlReader.buildStaticCredentials(\n accessKeyId,\n secretAccessKey,\n );\n } else {\n explicitCredentials = (await credsManager.getCredentialProvider())\n .sdkCredentialProvider;\n }\n\n const roleArn = integration.config.roleArn;\n if (roleArn) {\n return fromTemporaryCredentials({\n masterCredentials: explicitCredentials,\n params: {\n RoleSessionName: 'backstage-aws-code-commit-url-reader',\n RoleArn: roleArn,\n ExternalId: integration.config.externalId,\n },\n clientConfig: { region },\n });\n }\n\n return explicitCredentials;\n }\n\n private async buildCodeCommitClient(\n credsManager: AwsCredentialsManager,\n region: string,\n integration: AwsCodeCommitIntegration,\n ): Promise<CodeCommitClient> {\n const credentials = await AwsCodeCommitUrlReader.buildCredentials(\n credsManager,\n region,\n integration,\n );\n\n const codeCommit = new CodeCommitClient({\n customUserAgent: 'backstage-aws-codecommit-url-reader',\n region: region,\n credentials: credentials,\n });\n return codeCommit;\n }\n\n async readUrl(\n url: string,\n options?: UrlReaderServiceReadUrlOptions,\n ): Promise<UrlReaderServiceReadUrlResponse> {\n // etag and lastModifiedAfter are not supported by the CodeCommit API\n try {\n const { path, repositoryName, region, commitSpecifier } = parseUrl(\n url,\n true,\n );\n const codeCommitClient = await this.buildCodeCommitClient(\n this.credsManager,\n region,\n this.integration,\n );\n const abortController = new AbortController();\n\n const input: GetFileCommandInput = {\n repositoryName: repositoryName,\n commitSpecifier: commitSpecifier,\n filePath: path,\n };\n\n options?.signal?.addEventListener('abort', () => abortController.abort());\n const getObjectCommand = new GetFileCommand(input);\n const response: GetFileCommandOutput = await codeCommitClient.send(\n getObjectCommand,\n {\n abortSignal: abortController.signal,\n },\n );\n\n if (options?.etag && options.etag === response.commitId) {\n throw new NotModifiedError();\n }\n\n return ReadUrlResponseFactory.fromReadable(\n Readable.from([response?.fileContent] || []),\n {\n etag: response.commitId,\n },\n );\n } catch (e) {\n if (e.$metadata && e.$metadata.httpStatusCode === 304) {\n throw new NotModifiedError();\n }\n if (e.name && e.name === 'NotModifiedError') {\n throw new NotModifiedError();\n }\n\n throw new ForwardedError('Could not retrieve file from CodeCommit', e);\n }\n }\n\n async readTreePath(\n codeCommitClient: CodeCommitClient,\n abortSignal: any,\n path: string,\n repositoryName: string,\n commitSpecifier?: string,\n etag?: string,\n ): Promise<string[]> {\n const getFolderCommand = new GetFolderCommand({\n folderPath: path,\n repositoryName: repositoryName,\n commitSpecifier: commitSpecifier,\n });\n const response = await codeCommitClient.send(getFolderCommand, {\n abortSignal: abortSignal,\n });\n\n if (etag && etag === response.commitId) {\n throw new NotModifiedError();\n }\n\n const output: string[] = [];\n if (response.files) {\n response.files.forEach(file => {\n if (file.absolutePath) {\n output.push(file.absolutePath);\n }\n });\n }\n if (!response.subFolders) {\n return output;\n }\n\n for (const subFolder of response.subFolders) {\n if (subFolder.absolutePath) {\n output.push(\n ...(await this.readTreePath(\n codeCommitClient,\n abortSignal,\n subFolder.absolutePath,\n repositoryName,\n commitSpecifier,\n etag,\n )),\n );\n }\n }\n return output;\n }\n\n async readTree(\n url: string,\n options?: UrlReaderServiceReadTreeOptions,\n ): Promise<UrlReaderServiceReadTreeResponse> {\n // url: https://eu-west-1.console.aws.amazon.com/codesuite/codecommit/repositories/test-stijn-delete-techdocs/browse?region=eu-west-1\n try {\n const { path, repositoryName, region, commitSpecifier } = parseUrl(url);\n const codeCommitClient = await this.buildCodeCommitClient(\n this.credsManager,\n region,\n this.integration,\n );\n\n const abortController = new AbortController();\n options?.signal?.addEventListener('abort', () => abortController.abort());\n\n const allFiles: string[] = await this.readTreePath(\n codeCommitClient,\n abortController.signal,\n path,\n repositoryName,\n commitSpecifier,\n options?.etag,\n );\n const responses = [];\n\n for (let i = 0; i < allFiles.length; i++) {\n const getFileCommand = new GetFileCommand({\n repositoryName: repositoryName,\n filePath: String(allFiles[i]),\n commitSpecifier: commitSpecifier,\n });\n const response = await codeCommitClient.send(getFileCommand);\n const objectData = await Readable.from([response?.fileContent] || []);\n\n responses.push({\n data: objectData,\n path: relative(\n path.startsWith('/') ? path : `/${path}`,\n allFiles[i].startsWith('/') ? allFiles[i] : `/${allFiles[i]}`,\n ),\n });\n }\n\n return await this.deps.treeResponseFactory.fromReadableArray(responses);\n } catch (e) {\n if (e.name && e.name === 'NotModifiedError') {\n throw new NotModifiedError();\n }\n throw new ForwardedError(\n 'Could not retrieve file tree from CodeCommit',\n e,\n );\n }\n }\n\n async search(): Promise<UrlReaderServiceSearchResponse> {\n throw new Error('AwsCodeCommitReader does not implement search');\n }\n\n toString() {\n const secretAccessKey = this.integration.config.secretAccessKey;\n return `awsCodeCommit{host=${this.integration.config.host},authed=${Boolean(\n secretAccessKey,\n )}}`;\n }\n}\n"],"names":["repositoryName","commitSpecifier","ScmIntegrations","DefaultAwsCredentialsManager","fromTemporaryCredentials","CodeCommitClient","abortController","AbortController","GetFileCommand","NotModifiedError","ReadUrlResponseFactory","Readable","ForwardedError","GetFolderCommand","relative"],"mappings":"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"}
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var integrationAwsNode = require('@backstage/integration-aws-node');
|
|
4
|
+
var integration = require('@backstage/integration');
|
|
5
|
+
var errors = require('@backstage/errors');
|
|
6
|
+
var credentialProviders = require('@aws-sdk/credential-providers');
|
|
7
|
+
var clientS3 = require('@aws-sdk/client-s3');
|
|
8
|
+
var abortController = require('@aws-sdk/abort-controller');
|
|
9
|
+
var ReadUrlResponseFactory = require('./ReadUrlResponseFactory.cjs.js');
|
|
10
|
+
var stream = require('stream');
|
|
11
|
+
var posix = require('path/posix');
|
|
12
|
+
|
|
13
|
+
const DEFAULT_REGION = "us-east-1";
|
|
14
|
+
function parseUrl(url, config) {
|
|
15
|
+
const parsedUrl = new URL(url);
|
|
16
|
+
const pathname = parsedUrl.pathname.substring(1);
|
|
17
|
+
const host = parsedUrl.host;
|
|
18
|
+
if (config.host === "amazonaws.com" || config.host === "amazonaws.com.cn") {
|
|
19
|
+
const match = host.match(
|
|
20
|
+
/^(?:([a-z0-9.-]+)\.)?s3(?:[.-]([a-z0-9-]+))?\.amazonaws\.com(\.cn)?$/
|
|
21
|
+
);
|
|
22
|
+
if (!match) {
|
|
23
|
+
throw new Error(`Invalid AWS S3 URL ${url}`);
|
|
24
|
+
}
|
|
25
|
+
const [, hostBucket, hostRegion] = match;
|
|
26
|
+
if (config.s3ForcePathStyle || !hostBucket) {
|
|
27
|
+
const slashIndex = pathname.indexOf("/");
|
|
28
|
+
if (slashIndex < 0) {
|
|
29
|
+
throw new Error(
|
|
30
|
+
`Invalid path-style AWS S3 URL ${url}, does not contain bucket in the path`
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
path: pathname.substring(slashIndex + 1),
|
|
35
|
+
bucket: pathname.substring(0, slashIndex),
|
|
36
|
+
region: hostRegion ?? DEFAULT_REGION
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
path: pathname,
|
|
41
|
+
bucket: hostBucket,
|
|
42
|
+
region: hostRegion ?? DEFAULT_REGION
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
const usePathStyle = config.s3ForcePathStyle || host.length === config.host.length;
|
|
46
|
+
if (usePathStyle) {
|
|
47
|
+
const slashIndex = pathname.indexOf("/");
|
|
48
|
+
if (slashIndex < 0) {
|
|
49
|
+
throw new Error(
|
|
50
|
+
`Invalid path-style AWS S3 URL ${url}, does not contain bucket in the path`
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
path: pathname.substring(slashIndex + 1),
|
|
55
|
+
bucket: pathname.substring(0, slashIndex),
|
|
56
|
+
region: DEFAULT_REGION
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
path: pathname,
|
|
61
|
+
bucket: host.substring(0, host.length - config.host.length - 1),
|
|
62
|
+
region: DEFAULT_REGION
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
class AwsS3UrlReader {
|
|
66
|
+
constructor(credsManager, integration, deps) {
|
|
67
|
+
this.credsManager = credsManager;
|
|
68
|
+
this.integration = integration;
|
|
69
|
+
this.deps = deps;
|
|
70
|
+
}
|
|
71
|
+
static factory = ({ config, treeResponseFactory }) => {
|
|
72
|
+
const integrations = integration.ScmIntegrations.fromConfig(config);
|
|
73
|
+
const credsManager = integrationAwsNode.DefaultAwsCredentialsManager.fromConfig(config);
|
|
74
|
+
return integrations.awsS3.list().map((integration) => {
|
|
75
|
+
const reader = new AwsS3UrlReader(credsManager, integration, {
|
|
76
|
+
treeResponseFactory
|
|
77
|
+
});
|
|
78
|
+
const predicate = (url) => url.host.endsWith(integration.config.host);
|
|
79
|
+
return { reader, predicate };
|
|
80
|
+
});
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* If accessKeyId and secretAccessKey are missing, the standard credentials provider chain will be used:
|
|
84
|
+
* https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/DefaultAWSCredentialsProviderChain.html
|
|
85
|
+
*/
|
|
86
|
+
static buildStaticCredentials(accessKeyId, secretAccessKey) {
|
|
87
|
+
return async () => {
|
|
88
|
+
return {
|
|
89
|
+
accessKeyId,
|
|
90
|
+
secretAccessKey
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
static async buildCredentials(credsManager, region, integration) {
|
|
95
|
+
if (!integration) {
|
|
96
|
+
return (await credsManager.getCredentialProvider()).sdkCredentialProvider;
|
|
97
|
+
}
|
|
98
|
+
const accessKeyId = integration.config.accessKeyId;
|
|
99
|
+
const secretAccessKey = integration.config.secretAccessKey;
|
|
100
|
+
let explicitCredentials;
|
|
101
|
+
if (accessKeyId && secretAccessKey) {
|
|
102
|
+
explicitCredentials = AwsS3UrlReader.buildStaticCredentials(
|
|
103
|
+
accessKeyId,
|
|
104
|
+
secretAccessKey
|
|
105
|
+
);
|
|
106
|
+
} else {
|
|
107
|
+
explicitCredentials = (await credsManager.getCredentialProvider()).sdkCredentialProvider;
|
|
108
|
+
}
|
|
109
|
+
const roleArn = integration.config.roleArn;
|
|
110
|
+
if (roleArn) {
|
|
111
|
+
return credentialProviders.fromTemporaryCredentials({
|
|
112
|
+
masterCredentials: explicitCredentials,
|
|
113
|
+
params: {
|
|
114
|
+
RoleSessionName: "backstage-aws-s3-url-reader",
|
|
115
|
+
RoleArn: roleArn,
|
|
116
|
+
ExternalId: integration.config.externalId
|
|
117
|
+
},
|
|
118
|
+
clientConfig: { region }
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
return explicitCredentials;
|
|
122
|
+
}
|
|
123
|
+
async buildS3Client(credsManager, region, integration) {
|
|
124
|
+
const credentials = await AwsS3UrlReader.buildCredentials(
|
|
125
|
+
credsManager,
|
|
126
|
+
region,
|
|
127
|
+
integration
|
|
128
|
+
);
|
|
129
|
+
const s3 = new clientS3.S3Client({
|
|
130
|
+
customUserAgent: "backstage-aws-s3-url-reader",
|
|
131
|
+
region,
|
|
132
|
+
credentials,
|
|
133
|
+
endpoint: integration.config.endpoint,
|
|
134
|
+
forcePathStyle: integration.config.s3ForcePathStyle
|
|
135
|
+
});
|
|
136
|
+
return s3;
|
|
137
|
+
}
|
|
138
|
+
async retrieveS3ObjectData(stream$1) {
|
|
139
|
+
return new Promise((resolve, reject) => {
|
|
140
|
+
try {
|
|
141
|
+
const chunks = [];
|
|
142
|
+
stream$1.on("data", (chunk) => chunks.push(chunk));
|
|
143
|
+
stream$1.on(
|
|
144
|
+
"error",
|
|
145
|
+
(e) => reject(new errors.ForwardedError("Unable to read stream", e))
|
|
146
|
+
);
|
|
147
|
+
stream$1.on("end", () => resolve(stream.Readable.from(Buffer.concat(chunks))));
|
|
148
|
+
} catch (e) {
|
|
149
|
+
throw new errors.ForwardedError("Unable to parse the response data", e);
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
async read(url) {
|
|
154
|
+
const response = await this.readUrl(url);
|
|
155
|
+
return response.buffer();
|
|
156
|
+
}
|
|
157
|
+
async readUrl(url, options) {
|
|
158
|
+
const { etag, lastModifiedAfter } = options ?? {};
|
|
159
|
+
try {
|
|
160
|
+
const { path, bucket, region } = parseUrl(url, this.integration.config);
|
|
161
|
+
const s3Client = await this.buildS3Client(
|
|
162
|
+
this.credsManager,
|
|
163
|
+
region,
|
|
164
|
+
this.integration
|
|
165
|
+
);
|
|
166
|
+
const abortController$1 = new abortController.AbortController();
|
|
167
|
+
const params = {
|
|
168
|
+
Bucket: bucket,
|
|
169
|
+
Key: path,
|
|
170
|
+
...etag && { IfNoneMatch: etag },
|
|
171
|
+
...lastModifiedAfter && {
|
|
172
|
+
IfModifiedSince: lastModifiedAfter
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
options?.signal?.addEventListener("abort", () => abortController$1.abort());
|
|
176
|
+
const getObjectCommand = new clientS3.GetObjectCommand(params);
|
|
177
|
+
const response = await s3Client.send(getObjectCommand, {
|
|
178
|
+
abortSignal: abortController$1.signal
|
|
179
|
+
});
|
|
180
|
+
const s3ObjectData = await this.retrieveS3ObjectData(
|
|
181
|
+
response.Body
|
|
182
|
+
);
|
|
183
|
+
return ReadUrlResponseFactory.ReadUrlResponseFactory.fromReadable(s3ObjectData, {
|
|
184
|
+
etag: response.ETag,
|
|
185
|
+
lastModifiedAt: response.LastModified
|
|
186
|
+
});
|
|
187
|
+
} catch (e) {
|
|
188
|
+
if (e.$metadata && e.$metadata.httpStatusCode === 304) {
|
|
189
|
+
throw new errors.NotModifiedError();
|
|
190
|
+
}
|
|
191
|
+
throw new errors.ForwardedError("Could not retrieve file from S3", e);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
async readTree(url, options) {
|
|
195
|
+
try {
|
|
196
|
+
const { path, bucket, region } = parseUrl(url, this.integration.config);
|
|
197
|
+
const s3Client = await this.buildS3Client(
|
|
198
|
+
this.credsManager,
|
|
199
|
+
region,
|
|
200
|
+
this.integration
|
|
201
|
+
);
|
|
202
|
+
const abortController$1 = new abortController.AbortController();
|
|
203
|
+
const allObjects = [];
|
|
204
|
+
const responses = [];
|
|
205
|
+
let continuationToken;
|
|
206
|
+
let output;
|
|
207
|
+
do {
|
|
208
|
+
const listObjectsV2Command = new clientS3.ListObjectsV2Command({
|
|
209
|
+
Bucket: bucket,
|
|
210
|
+
ContinuationToken: continuationToken,
|
|
211
|
+
Prefix: path
|
|
212
|
+
});
|
|
213
|
+
options?.signal?.addEventListener(
|
|
214
|
+
"abort",
|
|
215
|
+
() => abortController$1.abort()
|
|
216
|
+
);
|
|
217
|
+
output = await s3Client.send(listObjectsV2Command, {
|
|
218
|
+
abortSignal: abortController$1.signal
|
|
219
|
+
});
|
|
220
|
+
if (output.Contents) {
|
|
221
|
+
output.Contents.forEach((contents) => {
|
|
222
|
+
allObjects.push(contents.Key);
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
continuationToken = output.NextContinuationToken;
|
|
226
|
+
} while (continuationToken);
|
|
227
|
+
for (let i = 0; i < allObjects.length; i++) {
|
|
228
|
+
const getObjectCommand = new clientS3.GetObjectCommand({
|
|
229
|
+
Bucket: bucket,
|
|
230
|
+
Key: String(allObjects[i])
|
|
231
|
+
});
|
|
232
|
+
const response = await s3Client.send(getObjectCommand);
|
|
233
|
+
const s3ObjectData = await this.retrieveS3ObjectData(
|
|
234
|
+
response.Body
|
|
235
|
+
);
|
|
236
|
+
responses.push({
|
|
237
|
+
data: s3ObjectData,
|
|
238
|
+
path: posix.relative(path, String(allObjects[i])),
|
|
239
|
+
lastModifiedAt: response?.LastModified ?? void 0
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
return await this.deps.treeResponseFactory.fromReadableArray(responses);
|
|
243
|
+
} catch (e) {
|
|
244
|
+
throw new errors.ForwardedError("Could not retrieve file tree from S3", e);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
async search() {
|
|
248
|
+
throw new Error("AwsS3Reader does not implement search");
|
|
249
|
+
}
|
|
250
|
+
toString() {
|
|
251
|
+
const secretAccessKey = this.integration.config.secretAccessKey;
|
|
252
|
+
return `awsS3{host=${this.integration.config.host},authed=${Boolean(
|
|
253
|
+
secretAccessKey
|
|
254
|
+
)}}`;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
exports.AwsS3UrlReader = AwsS3UrlReader;
|
|
259
|
+
exports.DEFAULT_REGION = DEFAULT_REGION;
|
|
260
|
+
exports.parseUrl = parseUrl;
|
|
261
|
+
//# sourceMappingURL=AwsS3UrlReader.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AwsS3UrlReader.cjs.js","sources":["../../../../src/entrypoints/urlReader/lib/AwsS3UrlReader.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n UrlReaderService,\n UrlReaderServiceReadTreeOptions,\n UrlReaderServiceReadTreeResponse,\n UrlReaderServiceReadUrlOptions,\n UrlReaderServiceReadUrlResponse,\n UrlReaderServiceSearchResponse,\n} from '@backstage/backend-plugin-api';\nimport { ReaderFactory, ReadTreeResponseFactory } from './types';\nimport {\n AwsCredentialsManager,\n DefaultAwsCredentialsManager,\n} from '@backstage/integration-aws-node';\nimport {\n AwsS3Integration,\n ScmIntegrations,\n AwsS3IntegrationConfig,\n} from '@backstage/integration';\nimport { ForwardedError, NotModifiedError } from '@backstage/errors';\nimport { fromTemporaryCredentials } from '@aws-sdk/credential-providers';\nimport { AwsCredentialIdentityProvider } from '@aws-sdk/types';\nimport {\n S3Client,\n ListObjectsV2Command,\n ListObjectsV2CommandOutput,\n GetObjectCommand,\n GetObjectCommandInput,\n} from '@aws-sdk/client-s3';\nimport { AbortController } from '@aws-sdk/abort-controller';\nimport { ReadUrlResponseFactory } from './ReadUrlResponseFactory';\nimport { Readable } from 'stream';\nimport { relative } from 'path/posix';\n\nexport const DEFAULT_REGION = 'us-east-1';\n\n/**\n * Path style URLs: https://s3.(region).amazonaws.com/(bucket)/(key)\n * The region can also be on the old form: https://s3-(region).amazonaws.com/(bucket)/(key)\n * Virtual hosted style URLs: https://(bucket).s3.(region).amazonaws.com/(key)\n * See https://docs.aws.amazon.com/AmazonS3/latest/userguide/VirtualHosting.html#path-style-access\n */\nexport function parseUrl(\n url: string,\n config: AwsS3IntegrationConfig,\n): { path: string; bucket: string; region: string } {\n const parsedUrl = new URL(url);\n\n /**\n * Removes the leading '/' from the pathname to be processed\n * as a parameter by AWS S3 SDK getObject method.\n */\n const pathname = parsedUrl.pathname.substring(1);\n const host = parsedUrl.host;\n\n // Treat Amazon hosted separately because it has special region logic\n if (config.host === 'amazonaws.com' || config.host === 'amazonaws.com.cn') {\n const match = host.match(\n /^(?:([a-z0-9.-]+)\\.)?s3(?:[.-]([a-z0-9-]+))?\\.amazonaws\\.com(\\.cn)?$/,\n );\n if (!match) {\n throw new Error(`Invalid AWS S3 URL ${url}`);\n }\n\n const [, hostBucket, hostRegion] = match;\n\n if (config.s3ForcePathStyle || !hostBucket) {\n const slashIndex = pathname.indexOf('/');\n if (slashIndex < 0) {\n throw new Error(\n `Invalid path-style AWS S3 URL ${url}, does not contain bucket in the path`,\n );\n }\n\n return {\n path: pathname.substring(slashIndex + 1),\n bucket: pathname.substring(0, slashIndex),\n region: hostRegion ?? DEFAULT_REGION,\n };\n }\n\n return {\n path: pathname,\n bucket: hostBucket,\n region: hostRegion ?? DEFAULT_REGION,\n };\n }\n\n const usePathStyle =\n config.s3ForcePathStyle || host.length === config.host.length;\n\n if (usePathStyle) {\n const slashIndex = pathname.indexOf('/');\n if (slashIndex < 0) {\n throw new Error(\n `Invalid path-style AWS S3 URL ${url}, does not contain bucket in the path`,\n );\n }\n\n return {\n path: pathname.substring(slashIndex + 1),\n bucket: pathname.substring(0, slashIndex),\n region: DEFAULT_REGION,\n };\n }\n\n return {\n path: pathname,\n bucket: host.substring(0, host.length - config.host.length - 1),\n region: DEFAULT_REGION,\n };\n}\n\n/**\n * Implements a {@link @backstage/backend-plugin-api#UrlReaderService} for AWS S3 buckets.\n *\n * @public\n */\nexport class AwsS3UrlReader implements UrlReaderService {\n static factory: ReaderFactory = ({ config, treeResponseFactory }) => {\n const integrations = ScmIntegrations.fromConfig(config);\n const credsManager = DefaultAwsCredentialsManager.fromConfig(config);\n\n return integrations.awsS3.list().map(integration => {\n const reader = new AwsS3UrlReader(credsManager, integration, {\n treeResponseFactory,\n });\n const predicate = (url: URL) =>\n url.host.endsWith(integration.config.host);\n return { reader, predicate };\n });\n };\n\n constructor(\n private readonly credsManager: AwsCredentialsManager,\n private readonly integration: AwsS3Integration,\n private readonly deps: {\n treeResponseFactory: ReadTreeResponseFactory;\n },\n ) {}\n\n /**\n * If accessKeyId and secretAccessKey are missing, the standard credentials provider chain will be used:\n * https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/DefaultAWSCredentialsProviderChain.html\n */\n private static buildStaticCredentials(\n accessKeyId: string,\n secretAccessKey: string,\n ): AwsCredentialIdentityProvider {\n return async () => {\n return {\n accessKeyId,\n secretAccessKey,\n };\n };\n }\n\n private static async buildCredentials(\n credsManager: AwsCredentialsManager,\n region: string,\n integration?: AwsS3Integration,\n ): Promise<AwsCredentialIdentityProvider> {\n // Fall back to the default credential chain if neither account ID\n // nor explicit credentials are provided\n if (!integration) {\n return (await credsManager.getCredentialProvider()).sdkCredentialProvider;\n }\n\n const accessKeyId = integration.config.accessKeyId;\n const secretAccessKey = integration.config.secretAccessKey;\n let explicitCredentials: AwsCredentialIdentityProvider;\n if (accessKeyId && secretAccessKey) {\n explicitCredentials = AwsS3UrlReader.buildStaticCredentials(\n accessKeyId,\n secretAccessKey,\n );\n } else {\n explicitCredentials = (await credsManager.getCredentialProvider())\n .sdkCredentialProvider;\n }\n\n const roleArn = integration.config.roleArn;\n if (roleArn) {\n return fromTemporaryCredentials({\n masterCredentials: explicitCredentials,\n params: {\n RoleSessionName: 'backstage-aws-s3-url-reader',\n RoleArn: roleArn,\n ExternalId: integration.config.externalId,\n },\n clientConfig: { region },\n });\n }\n\n return explicitCredentials;\n }\n\n private async buildS3Client(\n credsManager: AwsCredentialsManager,\n region: string,\n integration: AwsS3Integration,\n ): Promise<S3Client> {\n const credentials = await AwsS3UrlReader.buildCredentials(\n credsManager,\n region,\n integration,\n );\n\n const s3 = new S3Client({\n customUserAgent: 'backstage-aws-s3-url-reader',\n region: region,\n credentials: credentials,\n endpoint: integration.config.endpoint,\n forcePathStyle: integration.config.s3ForcePathStyle,\n });\n return s3;\n }\n\n private async retrieveS3ObjectData(stream: Readable): Promise<Readable> {\n return new Promise((resolve, reject) => {\n try {\n const chunks: any[] = [];\n stream.on('data', chunk => chunks.push(chunk));\n stream.on('error', (e: Error) =>\n reject(new ForwardedError('Unable to read stream', e)),\n );\n stream.on('end', () => resolve(Readable.from(Buffer.concat(chunks))));\n } catch (e) {\n throw new ForwardedError('Unable to parse the response data', e);\n }\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 const { etag, lastModifiedAfter } = options ?? {};\n\n try {\n const { path, bucket, region } = parseUrl(url, this.integration.config);\n const s3Client = await this.buildS3Client(\n this.credsManager,\n region,\n this.integration,\n );\n const abortController = new AbortController();\n\n const params: GetObjectCommandInput = {\n Bucket: bucket,\n Key: path,\n ...(etag && { IfNoneMatch: etag }),\n ...(lastModifiedAfter && {\n IfModifiedSince: lastModifiedAfter,\n }),\n };\n\n options?.signal?.addEventListener('abort', () => abortController.abort());\n const getObjectCommand = new GetObjectCommand(params);\n const response = await s3Client.send(getObjectCommand, {\n abortSignal: abortController.signal,\n });\n\n const s3ObjectData = await this.retrieveS3ObjectData(\n response.Body as Readable,\n );\n\n return ReadUrlResponseFactory.fromReadable(s3ObjectData, {\n etag: response.ETag,\n lastModifiedAt: response.LastModified,\n });\n } catch (e) {\n if (e.$metadata && e.$metadata.httpStatusCode === 304) {\n throw new NotModifiedError();\n }\n\n throw new ForwardedError('Could not retrieve file from S3', e);\n }\n }\n\n async readTree(\n url: string,\n options?: UrlReaderServiceReadTreeOptions,\n ): Promise<UrlReaderServiceReadTreeResponse> {\n try {\n const { path, bucket, region } = parseUrl(url, this.integration.config);\n const s3Client = await this.buildS3Client(\n this.credsManager,\n region,\n this.integration,\n );\n const abortController = new AbortController();\n const allObjects: String[] = [];\n const responses = [];\n let continuationToken: string | undefined;\n let output: ListObjectsV2CommandOutput;\n do {\n const listObjectsV2Command = new ListObjectsV2Command({\n Bucket: bucket,\n ContinuationToken: continuationToken,\n Prefix: path,\n });\n options?.signal?.addEventListener('abort', () =>\n abortController.abort(),\n );\n output = await s3Client.send(listObjectsV2Command, {\n abortSignal: abortController.signal,\n });\n if (output.Contents) {\n output.Contents.forEach(contents => {\n allObjects.push(contents.Key!);\n });\n }\n continuationToken = output.NextContinuationToken;\n } while (continuationToken);\n\n for (let i = 0; i < allObjects.length; i++) {\n const getObjectCommand = new GetObjectCommand({\n Bucket: bucket,\n Key: String(allObjects[i]),\n });\n const response = await s3Client.send(getObjectCommand);\n const s3ObjectData = await this.retrieveS3ObjectData(\n response.Body as Readable,\n );\n\n responses.push({\n data: s3ObjectData,\n path: relative(path, String(allObjects[i])),\n lastModifiedAt: response?.LastModified ?? undefined,\n });\n }\n\n return await this.deps.treeResponseFactory.fromReadableArray(responses);\n } catch (e) {\n throw new ForwardedError('Could not retrieve file tree from S3', e);\n }\n }\n\n async search(): Promise<UrlReaderServiceSearchResponse> {\n throw new Error('AwsS3Reader does not implement search');\n }\n\n toString() {\n const secretAccessKey = this.integration.config.secretAccessKey;\n return `awsS3{host=${this.integration.config.host},authed=${Boolean(\n secretAccessKey,\n )}}`;\n }\n}\n"],"names":["ScmIntegrations","DefaultAwsCredentialsManager","fromTemporaryCredentials","S3Client","stream","ForwardedError","Readable","abortController","AbortController","GetObjectCommand","ReadUrlResponseFactory","NotModifiedError","ListObjectsV2Command","relative"],"mappings":"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"}
|