@backstage/integration 2.1.2 → 2.1.3-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.
Files changed (129) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/ScmIntegrations.cjs.js.map +1 -1
  3. package/dist/ScmIntegrations.esm.js.map +1 -1
  4. package/dist/alpha/github/createGitHubCredentialsProviderFromConnection.cjs.js.map +1 -1
  5. package/dist/alpha/github/createGitHubCredentialsProviderFromConnection.esm.js.map +1 -1
  6. package/dist/awsCodeCommit/AwsCodeCommitIntegration.cjs.js +1 -0
  7. package/dist/awsCodeCommit/AwsCodeCommitIntegration.cjs.js.map +1 -1
  8. package/dist/awsCodeCommit/AwsCodeCommitIntegration.esm.js +1 -0
  9. package/dist/awsCodeCommit/AwsCodeCommitIntegration.esm.js.map +1 -1
  10. package/dist/awsCodeCommit/config.cjs.js.map +1 -1
  11. package/dist/awsCodeCommit/config.esm.js.map +1 -1
  12. package/dist/awsS3/AwsS3Integration.cjs.js +1 -0
  13. package/dist/awsS3/AwsS3Integration.cjs.js.map +1 -1
  14. package/dist/awsS3/AwsS3Integration.esm.js +1 -0
  15. package/dist/awsS3/AwsS3Integration.esm.js.map +1 -1
  16. package/dist/awsS3/config.cjs.js.map +1 -1
  17. package/dist/awsS3/config.esm.js.map +1 -1
  18. package/dist/azure/AzureIntegration.cjs.js +12 -1
  19. package/dist/azure/AzureIntegration.cjs.js.map +1 -1
  20. package/dist/azure/AzureIntegration.esm.js +12 -1
  21. package/dist/azure/AzureIntegration.esm.js.map +1 -1
  22. package/dist/azure/AzureUrl.cjs.js.map +1 -1
  23. package/dist/azure/AzureUrl.esm.js.map +1 -1
  24. package/dist/azure/CachedAzureDevOpsCredentialsProvider.cjs.js +1 -0
  25. package/dist/azure/CachedAzureDevOpsCredentialsProvider.cjs.js.map +1 -1
  26. package/dist/azure/CachedAzureDevOpsCredentialsProvider.esm.js +1 -0
  27. package/dist/azure/CachedAzureDevOpsCredentialsProvider.esm.js.map +1 -1
  28. package/dist/azure/DefaultAzureDevOpsCredentialsProvider.cjs.js +1 -0
  29. package/dist/azure/DefaultAzureDevOpsCredentialsProvider.cjs.js.map +1 -1
  30. package/dist/azure/DefaultAzureDevOpsCredentialsProvider.esm.js +1 -0
  31. package/dist/azure/DefaultAzureDevOpsCredentialsProvider.esm.js.map +1 -1
  32. package/dist/azure/ManagedIdentityClientAssertion.cjs.js.map +1 -1
  33. package/dist/azure/ManagedIdentityClientAssertion.esm.js.map +1 -1
  34. package/dist/azure/config.cjs.js.map +1 -1
  35. package/dist/azure/config.esm.js.map +1 -1
  36. package/dist/azure/core.cjs.js.map +1 -1
  37. package/dist/azure/core.esm.js.map +1 -1
  38. package/dist/azure/isVisualStudioDomain.cjs.js.map +1 -1
  39. package/dist/azure/isVisualStudioDomain.esm.js.map +1 -1
  40. package/dist/azureBlobStorage/AzureBlobStorageIntegration.cjs.js +1 -0
  41. package/dist/azureBlobStorage/AzureBlobStorageIntegration.cjs.js.map +1 -1
  42. package/dist/azureBlobStorage/AzureBlobStorageIntegration.esm.js +1 -0
  43. package/dist/azureBlobStorage/AzureBlobStorageIntegration.esm.js.map +1 -1
  44. package/dist/azureBlobStorage/DefaultAzureCredentialsProvider.cjs.js +1 -0
  45. package/dist/azureBlobStorage/DefaultAzureCredentialsProvider.cjs.js.map +1 -1
  46. package/dist/azureBlobStorage/DefaultAzureCredentialsProvider.esm.js +1 -0
  47. package/dist/azureBlobStorage/DefaultAzureCredentialsProvider.esm.js.map +1 -1
  48. package/dist/azureBlobStorage/config.cjs.js.map +1 -1
  49. package/dist/azureBlobStorage/config.esm.js.map +1 -1
  50. package/dist/bitbucketCloud/BitbucketCloudIntegration.cjs.js +1 -0
  51. package/dist/bitbucketCloud/BitbucketCloudIntegration.cjs.js.map +1 -1
  52. package/dist/bitbucketCloud/BitbucketCloudIntegration.esm.js +1 -0
  53. package/dist/bitbucketCloud/BitbucketCloudIntegration.esm.js.map +1 -1
  54. package/dist/bitbucketCloud/config.cjs.js.map +1 -1
  55. package/dist/bitbucketCloud/config.esm.js.map +1 -1
  56. package/dist/bitbucketCloud/core.cjs.js +17 -10
  57. package/dist/bitbucketCloud/core.cjs.js.map +1 -1
  58. package/dist/bitbucketCloud/core.esm.js +17 -10
  59. package/dist/bitbucketCloud/core.esm.js.map +1 -1
  60. package/dist/bitbucketServer/BitbucketServerIntegration.cjs.js +1 -0
  61. package/dist/bitbucketServer/BitbucketServerIntegration.cjs.js.map +1 -1
  62. package/dist/bitbucketServer/BitbucketServerIntegration.esm.js +1 -0
  63. package/dist/bitbucketServer/BitbucketServerIntegration.esm.js.map +1 -1
  64. package/dist/bitbucketServer/config.cjs.js.map +1 -1
  65. package/dist/bitbucketServer/config.esm.js.map +1 -1
  66. package/dist/bitbucketServer/core.cjs.js.map +1 -1
  67. package/dist/bitbucketServer/core.esm.js.map +1 -1
  68. package/dist/gerrit/GerritIntegration.cjs.js +1 -0
  69. package/dist/gerrit/GerritIntegration.cjs.js.map +1 -1
  70. package/dist/gerrit/GerritIntegration.esm.js +1 -0
  71. package/dist/gerrit/GerritIntegration.esm.js.map +1 -1
  72. package/dist/gerrit/config.cjs.js.map +1 -1
  73. package/dist/gerrit/config.esm.js.map +1 -1
  74. package/dist/gerrit/core.cjs.js.map +1 -1
  75. package/dist/gerrit/core.esm.js.map +1 -1
  76. package/dist/gitea/GiteaIntegration.cjs.js +1 -0
  77. package/dist/gitea/GiteaIntegration.cjs.js.map +1 -1
  78. package/dist/gitea/GiteaIntegration.esm.js +1 -0
  79. package/dist/gitea/GiteaIntegration.esm.js.map +1 -1
  80. package/dist/gitea/config.cjs.js.map +1 -1
  81. package/dist/gitea/config.esm.js.map +1 -1
  82. package/dist/gitea/core.cjs.js.map +1 -1
  83. package/dist/gitea/core.esm.js.map +1 -1
  84. package/dist/github/DefaultGithubCredentialsProvider.cjs.js.map +1 -1
  85. package/dist/github/DefaultGithubCredentialsProvider.esm.js.map +1 -1
  86. package/dist/github/GithubIntegration.cjs.js +1 -0
  87. package/dist/github/GithubIntegration.cjs.js.map +1 -1
  88. package/dist/github/GithubIntegration.esm.js +1 -0
  89. package/dist/github/GithubIntegration.esm.js.map +1 -1
  90. package/dist/github/SingleInstanceGithubCredentialsProvider.cjs.js.map +1 -1
  91. package/dist/github/SingleInstanceGithubCredentialsProvider.esm.js.map +1 -1
  92. package/dist/github/config.cjs.js.map +1 -1
  93. package/dist/github/config.esm.js.map +1 -1
  94. package/dist/github/core.cjs.js.map +1 -1
  95. package/dist/github/core.esm.js.map +1 -1
  96. package/dist/gitlab/DefaultGitlabCredentialsProvider.cjs.js +1 -0
  97. package/dist/gitlab/DefaultGitlabCredentialsProvider.cjs.js.map +1 -1
  98. package/dist/gitlab/DefaultGitlabCredentialsProvider.esm.js +1 -0
  99. package/dist/gitlab/DefaultGitlabCredentialsProvider.esm.js.map +1 -1
  100. package/dist/gitlab/GitLabIntegration.cjs.js +1 -0
  101. package/dist/gitlab/GitLabIntegration.cjs.js.map +1 -1
  102. package/dist/gitlab/GitLabIntegration.esm.js +1 -0
  103. package/dist/gitlab/GitLabIntegration.esm.js.map +1 -1
  104. package/dist/gitlab/SingleInstanceGitlabCredentialsProvider.cjs.js +1 -0
  105. package/dist/gitlab/SingleInstanceGitlabCredentialsProvider.cjs.js.map +1 -1
  106. package/dist/gitlab/SingleInstanceGitlabCredentialsProvider.esm.js +1 -0
  107. package/dist/gitlab/SingleInstanceGitlabCredentialsProvider.esm.js.map +1 -1
  108. package/dist/gitlab/config.cjs.js.map +1 -1
  109. package/dist/gitlab/config.esm.js.map +1 -1
  110. package/dist/gitlab/core.cjs.js.map +1 -1
  111. package/dist/gitlab/core.esm.js.map +1 -1
  112. package/dist/googleGcs/GoogleGcsIntegration.cjs.js +1 -0
  113. package/dist/googleGcs/GoogleGcsIntegration.cjs.js.map +1 -1
  114. package/dist/googleGcs/GoogleGcsIntegration.esm.js +1 -0
  115. package/dist/googleGcs/GoogleGcsIntegration.esm.js.map +1 -1
  116. package/dist/googleGcs/config.cjs.js.map +1 -1
  117. package/dist/googleGcs/config.esm.js.map +1 -1
  118. package/dist/harness/HarnessIntegration.cjs.js +1 -0
  119. package/dist/harness/HarnessIntegration.cjs.js.map +1 -1
  120. package/dist/harness/HarnessIntegration.esm.js +1 -0
  121. package/dist/harness/HarnessIntegration.esm.js.map +1 -1
  122. package/dist/harness/config.cjs.js.map +1 -1
  123. package/dist/harness/config.esm.js.map +1 -1
  124. package/dist/harness/core.cjs.js.map +1 -1
  125. package/dist/harness/core.esm.js.map +1 -1
  126. package/dist/helpers.cjs.js.map +1 -1
  127. package/dist/helpers.esm.js.map +1 -1
  128. package/dist/index.d.ts +4 -2
  129. package/package.json +7 -7
@@ -7,6 +7,7 @@ class DefaultAzureCredentialsManager {
7
7
  this.configProviders = configProviders;
8
8
  this.cachedCredentials = /* @__PURE__ */ new Map();
9
9
  }
10
+ configProviders;
10
11
  cachedCredentials;
11
12
  /**
12
13
  * Creates an instance of DefaultAzureCredentialsManager from a Backstage integration registry.
@@ -1 +1 @@
1
- {"version":3,"file":"DefaultAzureCredentialsProvider.cjs.js","sources":["../../src/azureBlobStorage/DefaultAzureCredentialsProvider.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 DefaultAzureCredential,\n ClientSecretCredential,\n TokenCredential,\n} from '@azure/identity';\nimport { AzureBlobStorageIntegrationConfig } from './config';\nimport { AzureCredentialsManager } from './types';\nimport { ScmIntegrationRegistry } from '../registry';\n\n/**\n * Default implementation of AzureCredentialsManager that supports multiple Azure Blob Storage integrations.\n * @public\n */\nexport class DefaultAzureCredentialsManager implements AzureCredentialsManager {\n private cachedCredentials: Map<string, TokenCredential>;\n\n private constructor(\n private readonly configProviders: Map<\n string,\n AzureBlobStorageIntegrationConfig\n >,\n ) {\n this.cachedCredentials = new Map<string, TokenCredential>();\n }\n\n /**\n * Creates an instance of DefaultAzureCredentialsManager from a Backstage integration registry.\n */\n static fromIntegrations(\n integrations: ScmIntegrationRegistry,\n ): DefaultAzureCredentialsManager {\n const configProviders = integrations.azureBlobStorage\n .list()\n .reduce((acc, integration) => {\n acc.set(\n integration.config.accountName || 'default',\n integration.config,\n );\n return acc;\n }, new Map<string, AzureBlobStorageIntegrationConfig>());\n\n return new DefaultAzureCredentialsManager(configProviders);\n }\n\n private createCredential(\n config: AzureBlobStorageIntegrationConfig,\n ): TokenCredential {\n if (\n config.aadCredential &&\n config.aadCredential.clientId &&\n config.aadCredential.clientSecret &&\n config.aadCredential.tenantId\n ) {\n return new ClientSecretCredential(\n config.aadCredential.tenantId,\n config.aadCredential.clientId,\n config.aadCredential.clientSecret,\n );\n }\n\n return new DefaultAzureCredential();\n }\n\n async getCredentials(accountName: string): Promise<TokenCredential> {\n if (this.cachedCredentials.has(accountName)) {\n return this.cachedCredentials.get(accountName)!;\n }\n\n const config = this.configProviders.get(accountName);\n if (!config) {\n throw new Error(`No configuration found for account: ${accountName}`);\n }\n\n const credential = this.createCredential(config);\n\n // Cache the credentials for future use\n this.cachedCredentials.set(accountName, credential);\n\n return credential;\n }\n}\n"],"names":["ClientSecretCredential","DefaultAzureCredential"],"mappings":";;;;AA6BO,MAAM,8BAAA,CAAkE;AAAA,EAGrE,YACW,eAAA,EAIjB;AAJiB,IAAA,IAAA,CAAA,eAAA,GAAA,eAAA;AAKjB,IAAA,IAAA,CAAK,iBAAA,uBAAwB,GAAA,EAA6B;AAAA,EAC5D;AAAA,EATQ,iBAAA;AAAA;AAAA;AAAA;AAAA,EAcR,OAAO,iBACL,YAAA,EACgC;AAChC,IAAA,MAAM,eAAA,GAAkB,aAAa,gBAAA,CAClC,IAAA,GACA,MAAA,CAAO,CAAC,KAAK,WAAA,KAAgB;AAC5B,MAAA,GAAA,CAAI,GAAA;AAAA,QACF,WAAA,CAAY,OAAO,WAAA,IAAe,SAAA;AAAA,QAClC,WAAA,CAAY;AAAA,OACd;AACA,MAAA,OAAO,GAAA;AAAA,IACT,CAAA,kBAAG,IAAI,GAAA,EAAgD,CAAA;AAEzD,IAAA,OAAO,IAAI,+BAA+B,eAAe,CAAA;AAAA,EAC3D;AAAA,EAEQ,iBACN,MAAA,EACiB;AACjB,IAAA,IACE,MAAA,CAAO,aAAA,IACP,MAAA,CAAO,aAAA,CAAc,QAAA,IACrB,OAAO,aAAA,CAAc,YAAA,IACrB,MAAA,CAAO,aAAA,CAAc,QAAA,EACrB;AACA,MAAA,OAAO,IAAIA,+BAAA;AAAA,QACT,OAAO,aAAA,CAAc,QAAA;AAAA,QACrB,OAAO,aAAA,CAAc,QAAA;AAAA,QACrB,OAAO,aAAA,CAAc;AAAA,OACvB;AAAA,IACF;AAEA,IAAA,OAAO,IAAIC,+BAAA,EAAuB;AAAA,EACpC;AAAA,EAEA,MAAM,eAAe,WAAA,EAA+C;AAClE,IAAA,IAAI,IAAA,CAAK,iBAAA,CAAkB,GAAA,CAAI,WAAW,CAAA,EAAG;AAC3C,MAAA,OAAO,IAAA,CAAK,iBAAA,CAAkB,GAAA,CAAI,WAAW,CAAA;AAAA,IAC/C;AAEA,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,eAAA,CAAgB,GAAA,CAAI,WAAW,CAAA;AACnD,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,oCAAA,EAAuC,WAAW,CAAA,CAAE,CAAA;AAAA,IACtE;AAEA,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,gBAAA,CAAiB,MAAM,CAAA;AAG/C,IAAA,IAAA,CAAK,iBAAA,CAAkB,GAAA,CAAI,WAAA,EAAa,UAAU,CAAA;AAElD,IAAA,OAAO,UAAA;AAAA,EACT;AACF;;;;"}
1
+ {"version":3,"file":"DefaultAzureCredentialsProvider.cjs.js","sources":["../../src/azureBlobStorage/DefaultAzureCredentialsProvider.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 DefaultAzureCredential,\n ClientSecretCredential,\n TokenCredential,\n} from '@azure/identity';\nimport { AzureBlobStorageIntegrationConfig } from './config';\nimport { AzureCredentialsManager } from './types';\nimport { ScmIntegrationRegistry } from '../registry';\n\n/**\n * Default implementation of AzureCredentialsManager that supports multiple Azure Blob Storage integrations.\n * @public\n */\nexport class DefaultAzureCredentialsManager implements AzureCredentialsManager {\n private cachedCredentials: Map<string, TokenCredential>;\n\n private constructor(\n private readonly configProviders: Map<\n string,\n AzureBlobStorageIntegrationConfig\n >,\n ) {\n this.cachedCredentials = new Map<string, TokenCredential>();\n }\n\n /**\n * Creates an instance of DefaultAzureCredentialsManager from a Backstage integration registry.\n */\n static fromIntegrations(\n integrations: ScmIntegrationRegistry,\n ): DefaultAzureCredentialsManager {\n const configProviders = integrations.azureBlobStorage\n .list()\n .reduce((acc, integration) => {\n acc.set(\n integration.config.accountName || 'default',\n integration.config,\n );\n return acc;\n }, new Map<string, AzureBlobStorageIntegrationConfig>());\n\n return new DefaultAzureCredentialsManager(configProviders);\n }\n\n private createCredential(\n config: AzureBlobStorageIntegrationConfig,\n ): TokenCredential {\n if (\n config.aadCredential &&\n config.aadCredential.clientId &&\n config.aadCredential.clientSecret &&\n config.aadCredential.tenantId\n ) {\n return new ClientSecretCredential(\n config.aadCredential.tenantId,\n config.aadCredential.clientId,\n config.aadCredential.clientSecret,\n );\n }\n\n return new DefaultAzureCredential();\n }\n\n async getCredentials(accountName: string): Promise<TokenCredential> {\n if (this.cachedCredentials.has(accountName)) {\n return this.cachedCredentials.get(accountName)!;\n }\n\n const config = this.configProviders.get(accountName);\n if (!config) {\n throw new Error(`No configuration found for account: ${accountName}`);\n }\n\n const credential = this.createCredential(config);\n\n // Cache the credentials for future use\n this.cachedCredentials.set(accountName, credential);\n\n return credential;\n }\n}\n"],"names":["ClientSecretCredential","DefaultAzureCredential"],"mappings":";;;;AA6BO,MAAM,8BAAA,CAAkE;AAAA,EAGrE,YACW,eAAA,EAIjB;AAJiB,IAAA,IAAA,CAAA,eAAA,GAAA,eAAA;AAKjB,IAAA,IAAA,CAAK,iBAAA,uBAAwB,GAAA,EAA6B;AAAA,EAC5D;AAAA,EANmB,eAAA;AAAA,EAHX,iBAAA;AAAA;AAAA;AAAA;AAAA,EAcR,OAAO,iBACL,YAAA,EACgC;AAChC,IAAA,MAAM,eAAA,GAAkB,aAAa,gBAAA,CAClC,IAAA,GACA,MAAA,CAAO,CAAC,KAAK,WAAA,KAAgB;AAC5B,MAAA,GAAA,CAAI,GAAA;AAAA,QACF,WAAA,CAAY,OAAO,WAAA,IAAe,SAAA;AAAA,QAClC,WAAA,CAAY;AAAA,OACd;AACA,MAAA,OAAO,GAAA;AAAA,IACT,CAAA,kBAAG,IAAI,GAAA,EAAgD,CAAA;AAEzD,IAAA,OAAO,IAAI,+BAA+B,eAAe,CAAA;AAAA,EAC3D;AAAA,EAEQ,iBACN,MAAA,EACiB;AACjB,IAAA,IACE,MAAA,CAAO,aAAA,IACP,MAAA,CAAO,aAAA,CAAc,QAAA,IACrB,OAAO,aAAA,CAAc,YAAA,IACrB,MAAA,CAAO,aAAA,CAAc,QAAA,EACrB;AACA,MAAA,OAAO,IAAIA,+BAAA;AAAA,QACT,OAAO,aAAA,CAAc,QAAA;AAAA,QACrB,OAAO,aAAA,CAAc,QAAA;AAAA,QACrB,OAAO,aAAA,CAAc;AAAA,OACvB;AAAA,IACF;AAEA,IAAA,OAAO,IAAIC,+BAAA,EAAuB;AAAA,EACpC;AAAA,EAEA,MAAM,eAAe,WAAA,EAA+C;AAClE,IAAA,IAAI,IAAA,CAAK,iBAAA,CAAkB,GAAA,CAAI,WAAW,CAAA,EAAG;AAC3C,MAAA,OAAO,IAAA,CAAK,iBAAA,CAAkB,GAAA,CAAI,WAAW,CAAA;AAAA,IAC/C;AAEA,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,eAAA,CAAgB,GAAA,CAAI,WAAW,CAAA;AACnD,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,oCAAA,EAAuC,WAAW,CAAA,CAAE,CAAA;AAAA,IACtE;AAEA,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,gBAAA,CAAiB,MAAM,CAAA;AAG/C,IAAA,IAAA,CAAK,iBAAA,CAAkB,GAAA,CAAI,WAAA,EAAa,UAAU,CAAA;AAElD,IAAA,OAAO,UAAA;AAAA,EACT;AACF;;"}
@@ -5,6 +5,7 @@ class DefaultAzureCredentialsManager {
5
5
  this.configProviders = configProviders;
6
6
  this.cachedCredentials = /* @__PURE__ */ new Map();
7
7
  }
8
+ configProviders;
8
9
  cachedCredentials;
9
10
  /**
10
11
  * Creates an instance of DefaultAzureCredentialsManager from a Backstage integration registry.
@@ -1 +1 @@
1
- {"version":3,"file":"DefaultAzureCredentialsProvider.esm.js","sources":["../../src/azureBlobStorage/DefaultAzureCredentialsProvider.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 DefaultAzureCredential,\n ClientSecretCredential,\n TokenCredential,\n} from '@azure/identity';\nimport { AzureBlobStorageIntegrationConfig } from './config';\nimport { AzureCredentialsManager } from './types';\nimport { ScmIntegrationRegistry } from '../registry';\n\n/**\n * Default implementation of AzureCredentialsManager that supports multiple Azure Blob Storage integrations.\n * @public\n */\nexport class DefaultAzureCredentialsManager implements AzureCredentialsManager {\n private cachedCredentials: Map<string, TokenCredential>;\n\n private constructor(\n private readonly configProviders: Map<\n string,\n AzureBlobStorageIntegrationConfig\n >,\n ) {\n this.cachedCredentials = new Map<string, TokenCredential>();\n }\n\n /**\n * Creates an instance of DefaultAzureCredentialsManager from a Backstage integration registry.\n */\n static fromIntegrations(\n integrations: ScmIntegrationRegistry,\n ): DefaultAzureCredentialsManager {\n const configProviders = integrations.azureBlobStorage\n .list()\n .reduce((acc, integration) => {\n acc.set(\n integration.config.accountName || 'default',\n integration.config,\n );\n return acc;\n }, new Map<string, AzureBlobStorageIntegrationConfig>());\n\n return new DefaultAzureCredentialsManager(configProviders);\n }\n\n private createCredential(\n config: AzureBlobStorageIntegrationConfig,\n ): TokenCredential {\n if (\n config.aadCredential &&\n config.aadCredential.clientId &&\n config.aadCredential.clientSecret &&\n config.aadCredential.tenantId\n ) {\n return new ClientSecretCredential(\n config.aadCredential.tenantId,\n config.aadCredential.clientId,\n config.aadCredential.clientSecret,\n );\n }\n\n return new DefaultAzureCredential();\n }\n\n async getCredentials(accountName: string): Promise<TokenCredential> {\n if (this.cachedCredentials.has(accountName)) {\n return this.cachedCredentials.get(accountName)!;\n }\n\n const config = this.configProviders.get(accountName);\n if (!config) {\n throw new Error(`No configuration found for account: ${accountName}`);\n }\n\n const credential = this.createCredential(config);\n\n // Cache the credentials for future use\n this.cachedCredentials.set(accountName, credential);\n\n return credential;\n }\n}\n"],"names":[],"mappings":";;AA6BO,MAAM,8BAAA,CAAkE;AAAA,EAGrE,YACW,eAAA,EAIjB;AAJiB,IAAA,IAAA,CAAA,eAAA,GAAA,eAAA;AAKjB,IAAA,IAAA,CAAK,iBAAA,uBAAwB,GAAA,EAA6B;AAAA,EAC5D;AAAA,EATQ,iBAAA;AAAA;AAAA;AAAA;AAAA,EAcR,OAAO,iBACL,YAAA,EACgC;AAChC,IAAA,MAAM,eAAA,GAAkB,aAAa,gBAAA,CAClC,IAAA,GACA,MAAA,CAAO,CAAC,KAAK,WAAA,KAAgB;AAC5B,MAAA,GAAA,CAAI,GAAA;AAAA,QACF,WAAA,CAAY,OAAO,WAAA,IAAe,SAAA;AAAA,QAClC,WAAA,CAAY;AAAA,OACd;AACA,MAAA,OAAO,GAAA;AAAA,IACT,CAAA,kBAAG,IAAI,GAAA,EAAgD,CAAA;AAEzD,IAAA,OAAO,IAAI,+BAA+B,eAAe,CAAA;AAAA,EAC3D;AAAA,EAEQ,iBACN,MAAA,EACiB;AACjB,IAAA,IACE,MAAA,CAAO,aAAA,IACP,MAAA,CAAO,aAAA,CAAc,QAAA,IACrB,OAAO,aAAA,CAAc,YAAA,IACrB,MAAA,CAAO,aAAA,CAAc,QAAA,EACrB;AACA,MAAA,OAAO,IAAI,sBAAA;AAAA,QACT,OAAO,aAAA,CAAc,QAAA;AAAA,QACrB,OAAO,aAAA,CAAc,QAAA;AAAA,QACrB,OAAO,aAAA,CAAc;AAAA,OACvB;AAAA,IACF;AAEA,IAAA,OAAO,IAAI,sBAAA,EAAuB;AAAA,EACpC;AAAA,EAEA,MAAM,eAAe,WAAA,EAA+C;AAClE,IAAA,IAAI,IAAA,CAAK,iBAAA,CAAkB,GAAA,CAAI,WAAW,CAAA,EAAG;AAC3C,MAAA,OAAO,IAAA,CAAK,iBAAA,CAAkB,GAAA,CAAI,WAAW,CAAA;AAAA,IAC/C;AAEA,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,eAAA,CAAgB,GAAA,CAAI,WAAW,CAAA;AACnD,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,oCAAA,EAAuC,WAAW,CAAA,CAAE,CAAA;AAAA,IACtE;AAEA,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,gBAAA,CAAiB,MAAM,CAAA;AAG/C,IAAA,IAAA,CAAK,iBAAA,CAAkB,GAAA,CAAI,WAAA,EAAa,UAAU,CAAA;AAElD,IAAA,OAAO,UAAA;AAAA,EACT;AACF;;;;"}
1
+ {"version":3,"file":"DefaultAzureCredentialsProvider.esm.js","sources":["../../src/azureBlobStorage/DefaultAzureCredentialsProvider.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 DefaultAzureCredential,\n ClientSecretCredential,\n TokenCredential,\n} from '@azure/identity';\nimport { AzureBlobStorageIntegrationConfig } from './config';\nimport { AzureCredentialsManager } from './types';\nimport { ScmIntegrationRegistry } from '../registry';\n\n/**\n * Default implementation of AzureCredentialsManager that supports multiple Azure Blob Storage integrations.\n * @public\n */\nexport class DefaultAzureCredentialsManager implements AzureCredentialsManager {\n private cachedCredentials: Map<string, TokenCredential>;\n\n private constructor(\n private readonly configProviders: Map<\n string,\n AzureBlobStorageIntegrationConfig\n >,\n ) {\n this.cachedCredentials = new Map<string, TokenCredential>();\n }\n\n /**\n * Creates an instance of DefaultAzureCredentialsManager from a Backstage integration registry.\n */\n static fromIntegrations(\n integrations: ScmIntegrationRegistry,\n ): DefaultAzureCredentialsManager {\n const configProviders = integrations.azureBlobStorage\n .list()\n .reduce((acc, integration) => {\n acc.set(\n integration.config.accountName || 'default',\n integration.config,\n );\n return acc;\n }, new Map<string, AzureBlobStorageIntegrationConfig>());\n\n return new DefaultAzureCredentialsManager(configProviders);\n }\n\n private createCredential(\n config: AzureBlobStorageIntegrationConfig,\n ): TokenCredential {\n if (\n config.aadCredential &&\n config.aadCredential.clientId &&\n config.aadCredential.clientSecret &&\n config.aadCredential.tenantId\n ) {\n return new ClientSecretCredential(\n config.aadCredential.tenantId,\n config.aadCredential.clientId,\n config.aadCredential.clientSecret,\n );\n }\n\n return new DefaultAzureCredential();\n }\n\n async getCredentials(accountName: string): Promise<TokenCredential> {\n if (this.cachedCredentials.has(accountName)) {\n return this.cachedCredentials.get(accountName)!;\n }\n\n const config = this.configProviders.get(accountName);\n if (!config) {\n throw new Error(`No configuration found for account: ${accountName}`);\n }\n\n const credential = this.createCredential(config);\n\n // Cache the credentials for future use\n this.cachedCredentials.set(accountName, credential);\n\n return credential;\n }\n}\n"],"names":[],"mappings":";;AA6BO,MAAM,8BAAA,CAAkE;AAAA,EAGrE,YACW,eAAA,EAIjB;AAJiB,IAAA,IAAA,CAAA,eAAA,GAAA,eAAA;AAKjB,IAAA,IAAA,CAAK,iBAAA,uBAAwB,GAAA,EAA6B;AAAA,EAC5D;AAAA,EANmB,eAAA;AAAA,EAHX,iBAAA;AAAA;AAAA;AAAA;AAAA,EAcR,OAAO,iBACL,YAAA,EACgC;AAChC,IAAA,MAAM,eAAA,GAAkB,aAAa,gBAAA,CAClC,IAAA,GACA,MAAA,CAAO,CAAC,KAAK,WAAA,KAAgB;AAC5B,MAAA,GAAA,CAAI,GAAA;AAAA,QACF,WAAA,CAAY,OAAO,WAAA,IAAe,SAAA;AAAA,QAClC,WAAA,CAAY;AAAA,OACd;AACA,MAAA,OAAO,GAAA;AAAA,IACT,CAAA,kBAAG,IAAI,GAAA,EAAgD,CAAA;AAEzD,IAAA,OAAO,IAAI,+BAA+B,eAAe,CAAA;AAAA,EAC3D;AAAA,EAEQ,iBACN,MAAA,EACiB;AACjB,IAAA,IACE,MAAA,CAAO,aAAA,IACP,MAAA,CAAO,aAAA,CAAc,QAAA,IACrB,OAAO,aAAA,CAAc,YAAA,IACrB,MAAA,CAAO,aAAA,CAAc,QAAA,EACrB;AACA,MAAA,OAAO,IAAI,sBAAA;AAAA,QACT,OAAO,aAAA,CAAc,QAAA;AAAA,QACrB,OAAO,aAAA,CAAc,QAAA;AAAA,QACrB,OAAO,aAAA,CAAc;AAAA,OACvB;AAAA,IACF;AAEA,IAAA,OAAO,IAAI,sBAAA,EAAuB;AAAA,EACpC;AAAA,EAEA,MAAM,eAAe,WAAA,EAA+C;AAClE,IAAA,IAAI,IAAA,CAAK,iBAAA,CAAkB,GAAA,CAAI,WAAW,CAAA,EAAG;AAC3C,MAAA,OAAO,IAAA,CAAK,iBAAA,CAAkB,GAAA,CAAI,WAAW,CAAA;AAAA,IAC/C;AAEA,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,eAAA,CAAgB,GAAA,CAAI,WAAW,CAAA;AACnD,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,oCAAA,EAAuC,WAAW,CAAA,CAAE,CAAA;AAAA,IACtE;AAEA,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,gBAAA,CAAiB,MAAM,CAAA;AAG/C,IAAA,IAAA,CAAK,iBAAA,CAAkB,GAAA,CAAI,WAAA,EAAa,UAAU,CAAA;AAElD,IAAA,OAAO,UAAA;AAAA,EACT;AACF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"config.cjs.js","sources":["../../src/azureBlobStorage/config.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 { Config } from '@backstage/config';\n\nconst AZURE_HOST = 'blob.core.windows.net';\n\n/**\n * The configuration parameters for a single Azure Blob Storage account.\n *\n * @public\n */\nexport type AzureBlobStorageIntegrationConfig = {\n /**\n * The name of the Azure Storage Account, e.g., \"mystorageaccount\".\n */\n accountName?: string;\n\n /**\n * The primary or secondary key for the Azure Storage Account.\n * Only required if connectionString or SAS token are not specified.\n */\n accountKey?: string;\n\n /**\n * A Shared Access Signature (SAS) token for limited access to resources.\n */\n sasToken?: string;\n\n /**\n * A full connection string for the Azure Storage Account.\n * This includes the account name, key, and endpoint details.\n */\n connectionString?: string;\n\n /**\n * Optional endpoint suffix for custom domains or sovereign clouds.\n * e.g., \"core.windows.net\" for public Azure or \"core.usgovcloudapi.net\" for US Government cloud.\n */\n endpointSuffix?: string;\n\n /**\n * The host of the target that this matches on, e.g., \"blob.core.windows.net\".\n */\n host: string;\n\n endpoint?: string;\n /**\n * Optional credential to use for Azure Active Directory authentication.\n */\n aadCredential?: {\n /**\n * The client ID of the Azure AD application.\n */\n clientId: string;\n\n /**\n * The tenant ID for Azure AD.\n */\n tenantId: string;\n\n /**\n * The client secret for the Azure AD application.\n */\n clientSecret: string;\n };\n};\n\n/**\n * Reads a single Azure Blob Storage integration config.\n *\n * @param config - The config object of a single integration.\n * @public\n */\nexport function readAzureBlobStorageIntegrationConfig(\n config: Config,\n): AzureBlobStorageIntegrationConfig {\n const endpoint = config.getOptionalString('endpoint');\n const accountName = config.getString('accountName');\n const accountKey = config.getOptionalString('accountKey')?.trim();\n const sasToken = config.getOptionalString('sasToken')?.trim();\n const connectionString = config.getOptionalString('connectionString')?.trim();\n const endpointSuffix = config.getOptionalString('endpointSuffix')?.trim();\n\n let host;\n let pathname;\n if (endpoint) {\n try {\n const url = new URL(endpoint);\n host = url.host;\n pathname = url.pathname;\n } catch {\n throw new Error(\n `invalid azureBlobStorage integration config, endpoint '${endpoint}' is not a valid URL`,\n );\n }\n if (pathname !== '/') {\n throw new Error(\n `invalid azureBlobStorage integration config, endpoints cannot contain path, got '${endpoint}'`,\n );\n }\n } else {\n host = AZURE_HOST;\n }\n const aadCredential = config.has('aadCredential')\n ? {\n clientId: config.getString('aadCredential.clientId'),\n tenantId: config.getString('aadCredential.tenantId'),\n clientSecret: config.getString('aadCredential.clientSecret')?.trim(),\n }\n : undefined;\n\n if (accountKey && sasToken) {\n throw new Error(\n `Invalid Azure Blob Storage config for ${accountName}: Both account key and SAS token cannot be used simultaneously.`,\n );\n }\n\n if (aadCredential && (accountKey || sasToken)) {\n throw new Error(\n `Invalid Azure Blob Storage config for ${accountName}: Cannot use both Azure AD credentials and account keys/SAS tokens for the same account.`,\n );\n }\n\n return {\n host,\n endpoint,\n accountName,\n accountKey,\n sasToken,\n connectionString,\n endpointSuffix,\n aadCredential,\n };\n}\n\n/**\n * Reads a set of Azure Blob Storage integration configs.\n *\n * @param configs - All of the integration config objects.\n * @public\n */\nexport function readAzureBlobStorageIntegrationConfigs(\n configs: Config[],\n): AzureBlobStorageIntegrationConfig[] {\n // First read all the explicit integrations\n const result = configs.map(readAzureBlobStorageIntegrationConfig);\n\n // If no explicit blob.core.windows.net integration was added, put one in the list as\n // a convenience\n if (!result.some(c => c.host === AZURE_HOST)) {\n result.push({\n host: AZURE_HOST,\n });\n }\n return result;\n}\n"],"names":[],"mappings":";;AAkBA,MAAM,UAAA,GAAa,uBAAA;AAqEZ,SAAS,sCACd,MAAA,EACmC;AACnC,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,iBAAA,CAAkB,UAAU,CAAA;AACpD,EAAA,MAAM,WAAA,GAAc,MAAA,CAAO,SAAA,CAAU,aAAa,CAAA;AAClD,EAAA,MAAM,UAAA,GAAa,MAAA,CAAO,iBAAA,CAAkB,YAAY,GAAG,IAAA,EAAK;AAChE,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,iBAAA,CAAkB,UAAU,GAAG,IAAA,EAAK;AAC5D,EAAA,MAAM,gBAAA,GAAmB,MAAA,CAAO,iBAAA,CAAkB,kBAAkB,GAAG,IAAA,EAAK;AAC5E,EAAA,MAAM,cAAA,GAAiB,MAAA,CAAO,iBAAA,CAAkB,gBAAgB,GAAG,IAAA,EAAK;AAExE,EAAA,IAAI,IAAA;AACJ,EAAA,IAAI,QAAA;AACJ,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,IAAI;AACF,MAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,QAAQ,CAAA;AAC5B,MAAA,IAAA,GAAO,GAAA,CAAI,IAAA;AACX,MAAA,QAAA,GAAW,GAAA,CAAI,QAAA;AAAA,IACjB,CAAA,CAAA,MAAQ;AACN,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,0DAA0D,QAAQ,CAAA,oBAAA;AAAA,OACpE;AAAA,IACF;AACA,IAAA,IAAI,aAAa,GAAA,EAAK;AACpB,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,oFAAoF,QAAQ,CAAA,CAAA;AAAA,OAC9F;AAAA,IACF;AAAA,EACF,CAAA,MAAO;AACL,IAAA,IAAA,GAAO,UAAA;AAAA,EACT;AACA,EAAA,MAAM,aAAA,GAAgB,MAAA,CAAO,GAAA,CAAI,eAAe,CAAA,GAC5C;AAAA,IACE,QAAA,EAAU,MAAA,CAAO,SAAA,CAAU,wBAAwB,CAAA;AAAA,IACnD,QAAA,EAAU,MAAA,CAAO,SAAA,CAAU,wBAAwB,CAAA;AAAA,IACnD,YAAA,EAAc,MAAA,CAAO,SAAA,CAAU,4BAA4B,GAAG,IAAA;AAAK,GACrE,GACA,MAAA;AAEJ,EAAA,IAAI,cAAc,QAAA,EAAU;AAC1B,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,yCAAyC,WAAW,CAAA,+DAAA;AAAA,KACtD;AAAA,EACF;AAEA,EAAA,IAAI,aAAA,KAAkB,cAAc,QAAA,CAAA,EAAW;AAC7C,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,yCAAyC,WAAW,CAAA,wFAAA;AAAA,KACtD;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,IAAA;AAAA,IACA,QAAA;AAAA,IACA,WAAA;AAAA,IACA,UAAA;AAAA,IACA,QAAA;AAAA,IACA,gBAAA;AAAA,IACA,cAAA;AAAA,IACA;AAAA,GACF;AACF;AAQO,SAAS,uCACd,OAAA,EACqC;AAErC,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,GAAA,CAAI,qCAAqC,CAAA;AAIhE,EAAA,IAAI,CAAC,MAAA,CAAO,IAAA,CAAK,OAAK,CAAA,CAAE,IAAA,KAAS,UAAU,CAAA,EAAG;AAC5C,IAAA,MAAA,CAAO,IAAA,CAAK;AAAA,MACV,IAAA,EAAM;AAAA,KACP,CAAA;AAAA,EACH;AACA,EAAA,OAAO,MAAA;AACT;;;;;"}
1
+ {"version":3,"file":"config.cjs.js","sources":["../../src/azureBlobStorage/config.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 { Config } from '@backstage/config';\n\nconst AZURE_HOST = 'blob.core.windows.net';\n\n/**\n * The configuration parameters for a single Azure Blob Storage account.\n *\n * @public\n */\nexport type AzureBlobStorageIntegrationConfig = {\n /**\n * The name of the Azure Storage Account, e.g., \"mystorageaccount\".\n */\n accountName?: string;\n\n /**\n * The primary or secondary key for the Azure Storage Account.\n * Only required if connectionString or SAS token are not specified.\n */\n accountKey?: string;\n\n /**\n * A Shared Access Signature (SAS) token for limited access to resources.\n */\n sasToken?: string;\n\n /**\n * A full connection string for the Azure Storage Account.\n * This includes the account name, key, and endpoint details.\n */\n connectionString?: string;\n\n /**\n * Optional endpoint suffix for custom domains or sovereign clouds.\n * e.g., \"core.windows.net\" for public Azure or \"core.usgovcloudapi.net\" for US Government cloud.\n */\n endpointSuffix?: string;\n\n /**\n * The host of the target that this matches on, e.g., \"blob.core.windows.net\".\n */\n host: string;\n\n endpoint?: string;\n /**\n * Optional credential to use for Azure Active Directory authentication.\n */\n aadCredential?: {\n /**\n * The client ID of the Azure AD application.\n */\n clientId: string;\n\n /**\n * The tenant ID for Azure AD.\n */\n tenantId: string;\n\n /**\n * The client secret for the Azure AD application.\n */\n clientSecret: string;\n };\n};\n\n/**\n * Reads a single Azure Blob Storage integration config.\n *\n * @param config - The config object of a single integration.\n * @public\n */\nexport function readAzureBlobStorageIntegrationConfig(\n config: Config,\n): AzureBlobStorageIntegrationConfig {\n const endpoint = config.getOptionalString('endpoint');\n const accountName = config.getString('accountName');\n const accountKey = config.getOptionalString('accountKey')?.trim();\n const sasToken = config.getOptionalString('sasToken')?.trim();\n const connectionString = config.getOptionalString('connectionString')?.trim();\n const endpointSuffix = config.getOptionalString('endpointSuffix')?.trim();\n\n let host;\n let pathname;\n if (endpoint) {\n try {\n const url = new URL(endpoint);\n host = url.host;\n pathname = url.pathname;\n } catch {\n throw new Error(\n `invalid azureBlobStorage integration config, endpoint '${endpoint}' is not a valid URL`,\n );\n }\n if (pathname !== '/') {\n throw new Error(\n `invalid azureBlobStorage integration config, endpoints cannot contain path, got '${endpoint}'`,\n );\n }\n } else {\n host = AZURE_HOST;\n }\n const aadCredential = config.has('aadCredential')\n ? {\n clientId: config.getString('aadCredential.clientId'),\n tenantId: config.getString('aadCredential.tenantId'),\n clientSecret: config.getString('aadCredential.clientSecret')?.trim(),\n }\n : undefined;\n\n if (accountKey && sasToken) {\n throw new Error(\n `Invalid Azure Blob Storage config for ${accountName}: Both account key and SAS token cannot be used simultaneously.`,\n );\n }\n\n if (aadCredential && (accountKey || sasToken)) {\n throw new Error(\n `Invalid Azure Blob Storage config for ${accountName}: Cannot use both Azure AD credentials and account keys/SAS tokens for the same account.`,\n );\n }\n\n return {\n host,\n endpoint,\n accountName,\n accountKey,\n sasToken,\n connectionString,\n endpointSuffix,\n aadCredential,\n };\n}\n\n/**\n * Reads a set of Azure Blob Storage integration configs.\n *\n * @param configs - All of the integration config objects.\n * @public\n */\nexport function readAzureBlobStorageIntegrationConfigs(\n configs: Config[],\n): AzureBlobStorageIntegrationConfig[] {\n // First read all the explicit integrations\n const result = configs.map(readAzureBlobStorageIntegrationConfig);\n\n // If no explicit blob.core.windows.net integration was added, put one in the list as\n // a convenience\n if (!result.some(c => c.host === AZURE_HOST)) {\n result.push({\n host: AZURE_HOST,\n });\n }\n return result;\n}\n"],"names":[],"mappings":";;AAkBA,MAAM,UAAA,GAAa,uBAAA;AAqEZ,SAAS,sCACd,MAAA,EACmC;AACnC,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,iBAAA,CAAkB,UAAU,CAAA;AACpD,EAAA,MAAM,WAAA,GAAc,MAAA,CAAO,SAAA,CAAU,aAAa,CAAA;AAClD,EAAA,MAAM,UAAA,GAAa,MAAA,CAAO,iBAAA,CAAkB,YAAY,GAAG,IAAA,EAAK;AAChE,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,iBAAA,CAAkB,UAAU,GAAG,IAAA,EAAK;AAC5D,EAAA,MAAM,gBAAA,GAAmB,MAAA,CAAO,iBAAA,CAAkB,kBAAkB,GAAG,IAAA,EAAK;AAC5E,EAAA,MAAM,cAAA,GAAiB,MAAA,CAAO,iBAAA,CAAkB,gBAAgB,GAAG,IAAA,EAAK;AAExE,EAAA,IAAI,IAAA;AACJ,EAAA,IAAI,QAAA;AACJ,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,IAAI;AACF,MAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,QAAQ,CAAA;AAC5B,MAAA,IAAA,GAAO,GAAA,CAAI,IAAA;AACX,MAAA,QAAA,GAAW,GAAA,CAAI,QAAA;AAAA,IACjB,CAAA,CAAA,MAAQ;AACN,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,0DAA0D,QAAQ,CAAA,oBAAA;AAAA,OACpE;AAAA,IACF;AACA,IAAA,IAAI,aAAa,GAAA,EAAK;AACpB,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,oFAAoF,QAAQ,CAAA,CAAA;AAAA,OAC9F;AAAA,IACF;AAAA,EACF,CAAA,MAAO;AACL,IAAA,IAAA,GAAO,UAAA;AAAA,EACT;AACA,EAAA,MAAM,aAAA,GAAgB,MAAA,CAAO,GAAA,CAAI,eAAe,CAAA,GAC5C;AAAA,IACE,QAAA,EAAU,MAAA,CAAO,SAAA,CAAU,wBAAwB,CAAA;AAAA,IACnD,QAAA,EAAU,MAAA,CAAO,SAAA,CAAU,wBAAwB,CAAA;AAAA,IACnD,YAAA,EAAc,MAAA,CAAO,SAAA,CAAU,4BAA4B,GAAG,IAAA;AAAK,GACrE,GACA,MAAA;AAEJ,EAAA,IAAI,cAAc,QAAA,EAAU;AAC1B,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,yCAAyC,WAAW,CAAA,+DAAA;AAAA,KACtD;AAAA,EACF;AAEA,EAAA,IAAI,aAAA,KAAkB,cAAc,QAAA,CAAA,EAAW;AAC7C,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,yCAAyC,WAAW,CAAA,wFAAA;AAAA,KACtD;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,IAAA;AAAA,IACA,QAAA;AAAA,IACA,WAAA;AAAA,IACA,UAAA;AAAA,IACA,QAAA;AAAA,IACA,gBAAA;AAAA,IACA,cAAA;AAAA,IACA;AAAA,GACF;AACF;AAQO,SAAS,uCACd,OAAA,EACqC;AAErC,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,GAAA,CAAI,qCAAqC,CAAA;AAIhE,EAAA,IAAI,CAAC,MAAA,CAAO,IAAA,CAAK,OAAK,CAAA,CAAE,IAAA,KAAS,UAAU,CAAA,EAAG;AAC5C,IAAA,MAAA,CAAO,IAAA,CAAK;AAAA,MACV,IAAA,EAAM;AAAA,KACP,CAAA;AAAA,EACH;AACA,EAAA,OAAO,MAAA;AACT;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"config.esm.js","sources":["../../src/azureBlobStorage/config.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 { Config } from '@backstage/config';\n\nconst AZURE_HOST = 'blob.core.windows.net';\n\n/**\n * The configuration parameters for a single Azure Blob Storage account.\n *\n * @public\n */\nexport type AzureBlobStorageIntegrationConfig = {\n /**\n * The name of the Azure Storage Account, e.g., \"mystorageaccount\".\n */\n accountName?: string;\n\n /**\n * The primary or secondary key for the Azure Storage Account.\n * Only required if connectionString or SAS token are not specified.\n */\n accountKey?: string;\n\n /**\n * A Shared Access Signature (SAS) token for limited access to resources.\n */\n sasToken?: string;\n\n /**\n * A full connection string for the Azure Storage Account.\n * This includes the account name, key, and endpoint details.\n */\n connectionString?: string;\n\n /**\n * Optional endpoint suffix for custom domains or sovereign clouds.\n * e.g., \"core.windows.net\" for public Azure or \"core.usgovcloudapi.net\" for US Government cloud.\n */\n endpointSuffix?: string;\n\n /**\n * The host of the target that this matches on, e.g., \"blob.core.windows.net\".\n */\n host: string;\n\n endpoint?: string;\n /**\n * Optional credential to use for Azure Active Directory authentication.\n */\n aadCredential?: {\n /**\n * The client ID of the Azure AD application.\n */\n clientId: string;\n\n /**\n * The tenant ID for Azure AD.\n */\n tenantId: string;\n\n /**\n * The client secret for the Azure AD application.\n */\n clientSecret: string;\n };\n};\n\n/**\n * Reads a single Azure Blob Storage integration config.\n *\n * @param config - The config object of a single integration.\n * @public\n */\nexport function readAzureBlobStorageIntegrationConfig(\n config: Config,\n): AzureBlobStorageIntegrationConfig {\n const endpoint = config.getOptionalString('endpoint');\n const accountName = config.getString('accountName');\n const accountKey = config.getOptionalString('accountKey')?.trim();\n const sasToken = config.getOptionalString('sasToken')?.trim();\n const connectionString = config.getOptionalString('connectionString')?.trim();\n const endpointSuffix = config.getOptionalString('endpointSuffix')?.trim();\n\n let host;\n let pathname;\n if (endpoint) {\n try {\n const url = new URL(endpoint);\n host = url.host;\n pathname = url.pathname;\n } catch {\n throw new Error(\n `invalid azureBlobStorage integration config, endpoint '${endpoint}' is not a valid URL`,\n );\n }\n if (pathname !== '/') {\n throw new Error(\n `invalid azureBlobStorage integration config, endpoints cannot contain path, got '${endpoint}'`,\n );\n }\n } else {\n host = AZURE_HOST;\n }\n const aadCredential = config.has('aadCredential')\n ? {\n clientId: config.getString('aadCredential.clientId'),\n tenantId: config.getString('aadCredential.tenantId'),\n clientSecret: config.getString('aadCredential.clientSecret')?.trim(),\n }\n : undefined;\n\n if (accountKey && sasToken) {\n throw new Error(\n `Invalid Azure Blob Storage config for ${accountName}: Both account key and SAS token cannot be used simultaneously.`,\n );\n }\n\n if (aadCredential && (accountKey || sasToken)) {\n throw new Error(\n `Invalid Azure Blob Storage config for ${accountName}: Cannot use both Azure AD credentials and account keys/SAS tokens for the same account.`,\n );\n }\n\n return {\n host,\n endpoint,\n accountName,\n accountKey,\n sasToken,\n connectionString,\n endpointSuffix,\n aadCredential,\n };\n}\n\n/**\n * Reads a set of Azure Blob Storage integration configs.\n *\n * @param configs - All of the integration config objects.\n * @public\n */\nexport function readAzureBlobStorageIntegrationConfigs(\n configs: Config[],\n): AzureBlobStorageIntegrationConfig[] {\n // First read all the explicit integrations\n const result = configs.map(readAzureBlobStorageIntegrationConfig);\n\n // If no explicit blob.core.windows.net integration was added, put one in the list as\n // a convenience\n if (!result.some(c => c.host === AZURE_HOST)) {\n result.push({\n host: AZURE_HOST,\n });\n }\n return result;\n}\n"],"names":[],"mappings":"AAkBA,MAAM,UAAA,GAAa,uBAAA;AAqEZ,SAAS,sCACd,MAAA,EACmC;AACnC,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,iBAAA,CAAkB,UAAU,CAAA;AACpD,EAAA,MAAM,WAAA,GAAc,MAAA,CAAO,SAAA,CAAU,aAAa,CAAA;AAClD,EAAA,MAAM,UAAA,GAAa,MAAA,CAAO,iBAAA,CAAkB,YAAY,GAAG,IAAA,EAAK;AAChE,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,iBAAA,CAAkB,UAAU,GAAG,IAAA,EAAK;AAC5D,EAAA,MAAM,gBAAA,GAAmB,MAAA,CAAO,iBAAA,CAAkB,kBAAkB,GAAG,IAAA,EAAK;AAC5E,EAAA,MAAM,cAAA,GAAiB,MAAA,CAAO,iBAAA,CAAkB,gBAAgB,GAAG,IAAA,EAAK;AAExE,EAAA,IAAI,IAAA;AACJ,EAAA,IAAI,QAAA;AACJ,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,IAAI;AACF,MAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,QAAQ,CAAA;AAC5B,MAAA,IAAA,GAAO,GAAA,CAAI,IAAA;AACX,MAAA,QAAA,GAAW,GAAA,CAAI,QAAA;AAAA,IACjB,CAAA,CAAA,MAAQ;AACN,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,0DAA0D,QAAQ,CAAA,oBAAA;AAAA,OACpE;AAAA,IACF;AACA,IAAA,IAAI,aAAa,GAAA,EAAK;AACpB,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,oFAAoF,QAAQ,CAAA,CAAA;AAAA,OAC9F;AAAA,IACF;AAAA,EACF,CAAA,MAAO;AACL,IAAA,IAAA,GAAO,UAAA;AAAA,EACT;AACA,EAAA,MAAM,aAAA,GAAgB,MAAA,CAAO,GAAA,CAAI,eAAe,CAAA,GAC5C;AAAA,IACE,QAAA,EAAU,MAAA,CAAO,SAAA,CAAU,wBAAwB,CAAA;AAAA,IACnD,QAAA,EAAU,MAAA,CAAO,SAAA,CAAU,wBAAwB,CAAA;AAAA,IACnD,YAAA,EAAc,MAAA,CAAO,SAAA,CAAU,4BAA4B,GAAG,IAAA;AAAK,GACrE,GACA,MAAA;AAEJ,EAAA,IAAI,cAAc,QAAA,EAAU;AAC1B,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,yCAAyC,WAAW,CAAA,+DAAA;AAAA,KACtD;AAAA,EACF;AAEA,EAAA,IAAI,aAAA,KAAkB,cAAc,QAAA,CAAA,EAAW;AAC7C,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,yCAAyC,WAAW,CAAA,wFAAA;AAAA,KACtD;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,IAAA;AAAA,IACA,QAAA;AAAA,IACA,WAAA;AAAA,IACA,UAAA;AAAA,IACA,QAAA;AAAA,IACA,gBAAA;AAAA,IACA,cAAA;AAAA,IACA;AAAA,GACF;AACF;AAQO,SAAS,uCACd,OAAA,EACqC;AAErC,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,GAAA,CAAI,qCAAqC,CAAA;AAIhE,EAAA,IAAI,CAAC,MAAA,CAAO,IAAA,CAAK,OAAK,CAAA,CAAE,IAAA,KAAS,UAAU,CAAA,EAAG;AAC5C,IAAA,MAAA,CAAO,IAAA,CAAK;AAAA,MACV,IAAA,EAAM;AAAA,KACP,CAAA;AAAA,EACH;AACA,EAAA,OAAO,MAAA;AACT;;;;"}
1
+ {"version":3,"file":"config.esm.js","sources":["../../src/azureBlobStorage/config.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 { Config } from '@backstage/config';\n\nconst AZURE_HOST = 'blob.core.windows.net';\n\n/**\n * The configuration parameters for a single Azure Blob Storage account.\n *\n * @public\n */\nexport type AzureBlobStorageIntegrationConfig = {\n /**\n * The name of the Azure Storage Account, e.g., \"mystorageaccount\".\n */\n accountName?: string;\n\n /**\n * The primary or secondary key for the Azure Storage Account.\n * Only required if connectionString or SAS token are not specified.\n */\n accountKey?: string;\n\n /**\n * A Shared Access Signature (SAS) token for limited access to resources.\n */\n sasToken?: string;\n\n /**\n * A full connection string for the Azure Storage Account.\n * This includes the account name, key, and endpoint details.\n */\n connectionString?: string;\n\n /**\n * Optional endpoint suffix for custom domains or sovereign clouds.\n * e.g., \"core.windows.net\" for public Azure or \"core.usgovcloudapi.net\" for US Government cloud.\n */\n endpointSuffix?: string;\n\n /**\n * The host of the target that this matches on, e.g., \"blob.core.windows.net\".\n */\n host: string;\n\n endpoint?: string;\n /**\n * Optional credential to use for Azure Active Directory authentication.\n */\n aadCredential?: {\n /**\n * The client ID of the Azure AD application.\n */\n clientId: string;\n\n /**\n * The tenant ID for Azure AD.\n */\n tenantId: string;\n\n /**\n * The client secret for the Azure AD application.\n */\n clientSecret: string;\n };\n};\n\n/**\n * Reads a single Azure Blob Storage integration config.\n *\n * @param config - The config object of a single integration.\n * @public\n */\nexport function readAzureBlobStorageIntegrationConfig(\n config: Config,\n): AzureBlobStorageIntegrationConfig {\n const endpoint = config.getOptionalString('endpoint');\n const accountName = config.getString('accountName');\n const accountKey = config.getOptionalString('accountKey')?.trim();\n const sasToken = config.getOptionalString('sasToken')?.trim();\n const connectionString = config.getOptionalString('connectionString')?.trim();\n const endpointSuffix = config.getOptionalString('endpointSuffix')?.trim();\n\n let host;\n let pathname;\n if (endpoint) {\n try {\n const url = new URL(endpoint);\n host = url.host;\n pathname = url.pathname;\n } catch {\n throw new Error(\n `invalid azureBlobStorage integration config, endpoint '${endpoint}' is not a valid URL`,\n );\n }\n if (pathname !== '/') {\n throw new Error(\n `invalid azureBlobStorage integration config, endpoints cannot contain path, got '${endpoint}'`,\n );\n }\n } else {\n host = AZURE_HOST;\n }\n const aadCredential = config.has('aadCredential')\n ? {\n clientId: config.getString('aadCredential.clientId'),\n tenantId: config.getString('aadCredential.tenantId'),\n clientSecret: config.getString('aadCredential.clientSecret')?.trim(),\n }\n : undefined;\n\n if (accountKey && sasToken) {\n throw new Error(\n `Invalid Azure Blob Storage config for ${accountName}: Both account key and SAS token cannot be used simultaneously.`,\n );\n }\n\n if (aadCredential && (accountKey || sasToken)) {\n throw new Error(\n `Invalid Azure Blob Storage config for ${accountName}: Cannot use both Azure AD credentials and account keys/SAS tokens for the same account.`,\n );\n }\n\n return {\n host,\n endpoint,\n accountName,\n accountKey,\n sasToken,\n connectionString,\n endpointSuffix,\n aadCredential,\n };\n}\n\n/**\n * Reads a set of Azure Blob Storage integration configs.\n *\n * @param configs - All of the integration config objects.\n * @public\n */\nexport function readAzureBlobStorageIntegrationConfigs(\n configs: Config[],\n): AzureBlobStorageIntegrationConfig[] {\n // First read all the explicit integrations\n const result = configs.map(readAzureBlobStorageIntegrationConfig);\n\n // If no explicit blob.core.windows.net integration was added, put one in the list as\n // a convenience\n if (!result.some(c => c.host === AZURE_HOST)) {\n result.push({\n host: AZURE_HOST,\n });\n }\n return result;\n}\n"],"names":[],"mappings":"AAkBA,MAAM,UAAA,GAAa,uBAAA;AAqEZ,SAAS,sCACd,MAAA,EACmC;AACnC,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,iBAAA,CAAkB,UAAU,CAAA;AACpD,EAAA,MAAM,WAAA,GAAc,MAAA,CAAO,SAAA,CAAU,aAAa,CAAA;AAClD,EAAA,MAAM,UAAA,GAAa,MAAA,CAAO,iBAAA,CAAkB,YAAY,GAAG,IAAA,EAAK;AAChE,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,iBAAA,CAAkB,UAAU,GAAG,IAAA,EAAK;AAC5D,EAAA,MAAM,gBAAA,GAAmB,MAAA,CAAO,iBAAA,CAAkB,kBAAkB,GAAG,IAAA,EAAK;AAC5E,EAAA,MAAM,cAAA,GAAiB,MAAA,CAAO,iBAAA,CAAkB,gBAAgB,GAAG,IAAA,EAAK;AAExE,EAAA,IAAI,IAAA;AACJ,EAAA,IAAI,QAAA;AACJ,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,IAAI;AACF,MAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,QAAQ,CAAA;AAC5B,MAAA,IAAA,GAAO,GAAA,CAAI,IAAA;AACX,MAAA,QAAA,GAAW,GAAA,CAAI,QAAA;AAAA,IACjB,CAAA,CAAA,MAAQ;AACN,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,0DAA0D,QAAQ,CAAA,oBAAA;AAAA,OACpE;AAAA,IACF;AACA,IAAA,IAAI,aAAa,GAAA,EAAK;AACpB,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,oFAAoF,QAAQ,CAAA,CAAA;AAAA,OAC9F;AAAA,IACF;AAAA,EACF,CAAA,MAAO;AACL,IAAA,IAAA,GAAO,UAAA;AAAA,EACT;AACA,EAAA,MAAM,aAAA,GAAgB,MAAA,CAAO,GAAA,CAAI,eAAe,CAAA,GAC5C;AAAA,IACE,QAAA,EAAU,MAAA,CAAO,SAAA,CAAU,wBAAwB,CAAA;AAAA,IACnD,QAAA,EAAU,MAAA,CAAO,SAAA,CAAU,wBAAwB,CAAA;AAAA,IACnD,YAAA,EAAc,MAAA,CAAO,SAAA,CAAU,4BAA4B,GAAG,IAAA;AAAK,GACrE,GACA,MAAA;AAEJ,EAAA,IAAI,cAAc,QAAA,EAAU;AAC1B,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,yCAAyC,WAAW,CAAA,+DAAA;AAAA,KACtD;AAAA,EACF;AAEA,EAAA,IAAI,aAAA,KAAkB,cAAc,QAAA,CAAA,EAAW;AAC7C,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,yCAAyC,WAAW,CAAA,wFAAA;AAAA,KACtD;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,IAAA;AAAA,IACA,QAAA;AAAA,IACA,WAAA;AAAA,IACA,UAAA;AAAA,IACA,QAAA;AAAA,IACA,gBAAA;AAAA,IACA,cAAA;AAAA,IACA;AAAA,GACF;AACF;AAQO,SAAS,uCACd,OAAA,EACqC;AAErC,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,GAAA,CAAI,qCAAqC,CAAA;AAIhE,EAAA,IAAI,CAAC,MAAA,CAAO,IAAA,CAAK,OAAK,CAAA,CAAE,IAAA,KAAS,UAAU,CAAA,EAAG;AAC5C,IAAA,MAAA,CAAO,IAAA,CAAK;AAAA,MACV,IAAA,EAAM;AAAA,KACP,CAAA;AAAA,EACH;AACA,EAAA,OAAO,MAAA;AACT;;"}
@@ -12,6 +12,7 @@ class BitbucketCloudIntegration {
12
12
  constructor(integrationConfig) {
13
13
  this.integrationConfig = integrationConfig;
14
14
  }
15
+ integrationConfig;
15
16
  static factory = ({
16
17
  config: config$1
17
18
  }) => {
@@ -1 +1 @@
1
- {"version":3,"file":"BitbucketCloudIntegration.cjs.js","sources":["../../src/bitbucketCloud/BitbucketCloudIntegration.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 parseGitUrl from 'git-url-parse';\nimport { basicIntegrations, defaultScmResolveUrl } from '../helpers';\nimport { ScmIntegration, ScmIntegrationsFactory } from '../types';\nimport {\n BitbucketCloudIntegrationConfig,\n readBitbucketCloudIntegrationConfigs,\n} from './config';\n\n/**\n * A Bitbucket Cloud based integration.\n *\n * @public\n */\nexport class BitbucketCloudIntegration implements ScmIntegration {\n static factory: ScmIntegrationsFactory<BitbucketCloudIntegration> = ({\n config,\n }) => {\n const configs = readBitbucketCloudIntegrationConfigs(\n config.getOptionalConfigArray('integrations.bitbucketCloud') ?? [],\n );\n return basicIntegrations(\n configs.map(c => new BitbucketCloudIntegration(c)),\n i => i.config.host,\n );\n };\n\n constructor(\n private readonly integrationConfig: BitbucketCloudIntegrationConfig,\n ) {}\n\n get type(): string {\n return 'bitbucketCloud';\n }\n\n get title(): string {\n return this.integrationConfig.host;\n }\n\n get config(): BitbucketCloudIntegrationConfig {\n return this.integrationConfig;\n }\n\n resolveUrl(options: {\n url: string;\n base: string;\n lineNumber?: number;\n }): string {\n const resolved = defaultScmResolveUrl(options);\n\n // Bitbucket Cloud line numbers use the syntax #lines-42, rather than #L42\n if (options.lineNumber) {\n const url = new URL(resolved);\n\n url.hash = `lines-${options.lineNumber}`;\n return url.toString();\n }\n\n return resolved;\n }\n\n resolveEditUrl(url: string): string {\n const urlData = parseGitUrl(url);\n const editUrl = new URL(url);\n\n editUrl.searchParams.set('mode', 'edit');\n editUrl.searchParams.set('at', urlData.ref);\n return editUrl.toString();\n }\n}\n"],"names":["config","readBitbucketCloudIntegrationConfigs","basicIntegrations","defaultScmResolveUrl","parseGitUrl"],"mappings":";;;;;;;;;;AA6BO,MAAM,yBAAA,CAAoD;AAAA,EAa/D,YACmB,iBAAA,EACjB;AADiB,IAAA,IAAA,CAAA,iBAAA,GAAA,iBAAA;AAAA,EAChB;AAAA,EAdH,OAAO,UAA6D,CAAC;AAAA,YACnEA;AAAA,GACF,KAAM;AACJ,IAAA,MAAM,OAAA,GAAUC,2CAAA;AAAA,MACdD,QAAA,CAAO,sBAAA,CAAuB,6BAA6B,CAAA,IAAK;AAAC,KACnE;AACA,IAAA,OAAOE,yBAAA;AAAA,MACL,QAAQ,GAAA,CAAI,CAAA,CAAA,KAAK,IAAI,yBAAA,CAA0B,CAAC,CAAC,CAAA;AAAA,MACjD,CAAA,CAAA,KAAK,EAAE,MAAA,CAAO;AAAA,KAChB;AAAA,EACF,CAAA;AAAA,EAMA,IAAI,IAAA,GAAe;AACjB,IAAA,OAAO,gBAAA;AAAA,EACT;AAAA,EAEA,IAAI,KAAA,GAAgB;AAClB,IAAA,OAAO,KAAK,iBAAA,CAAkB,IAAA;AAAA,EAChC;AAAA,EAEA,IAAI,MAAA,GAA0C;AAC5C,IAAA,OAAO,IAAA,CAAK,iBAAA;AAAA,EACd;AAAA,EAEA,WAAW,OAAA,EAIA;AACT,IAAA,MAAM,QAAA,GAAWC,6BAAqB,OAAO,CAAA;AAG7C,IAAA,IAAI,QAAQ,UAAA,EAAY;AACtB,MAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,QAAQ,CAAA;AAE5B,MAAA,GAAA,CAAI,IAAA,GAAO,CAAA,MAAA,EAAS,OAAA,CAAQ,UAAU,CAAA,CAAA;AACtC,MAAA,OAAO,IAAI,QAAA,EAAS;AAAA,IACtB;AAEA,IAAA,OAAO,QAAA;AAAA,EACT;AAAA,EAEA,eAAe,GAAA,EAAqB;AAClC,IAAA,MAAM,OAAA,GAAUC,6BAAY,GAAG,CAAA;AAC/B,IAAA,MAAM,OAAA,GAAU,IAAI,GAAA,CAAI,GAAG,CAAA;AAE3B,IAAA,OAAA,CAAQ,YAAA,CAAa,GAAA,CAAI,MAAA,EAAQ,MAAM,CAAA;AACvC,IAAA,OAAA,CAAQ,YAAA,CAAa,GAAA,CAAI,IAAA,EAAM,OAAA,CAAQ,GAAG,CAAA;AAC1C,IAAA,OAAO,QAAQ,QAAA,EAAS;AAAA,EAC1B;AACF;;;;"}
1
+ {"version":3,"file":"BitbucketCloudIntegration.cjs.js","sources":["../../src/bitbucketCloud/BitbucketCloudIntegration.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 parseGitUrl from 'git-url-parse';\nimport { basicIntegrations, defaultScmResolveUrl } from '../helpers';\nimport { ScmIntegration, ScmIntegrationsFactory } from '../types';\nimport {\n BitbucketCloudIntegrationConfig,\n readBitbucketCloudIntegrationConfigs,\n} from './config';\n\n/**\n * A Bitbucket Cloud based integration.\n *\n * @public\n */\nexport class BitbucketCloudIntegration implements ScmIntegration {\n static factory: ScmIntegrationsFactory<BitbucketCloudIntegration> = ({\n config,\n }) => {\n const configs = readBitbucketCloudIntegrationConfigs(\n config.getOptionalConfigArray('integrations.bitbucketCloud') ?? [],\n );\n return basicIntegrations(\n configs.map(c => new BitbucketCloudIntegration(c)),\n i => i.config.host,\n );\n };\n\n constructor(\n private readonly integrationConfig: BitbucketCloudIntegrationConfig,\n ) {}\n\n get type(): string {\n return 'bitbucketCloud';\n }\n\n get title(): string {\n return this.integrationConfig.host;\n }\n\n get config(): BitbucketCloudIntegrationConfig {\n return this.integrationConfig;\n }\n\n resolveUrl(options: {\n url: string;\n base: string;\n lineNumber?: number;\n }): string {\n const resolved = defaultScmResolveUrl(options);\n\n // Bitbucket Cloud line numbers use the syntax #lines-42, rather than #L42\n if (options.lineNumber) {\n const url = new URL(resolved);\n\n url.hash = `lines-${options.lineNumber}`;\n return url.toString();\n }\n\n return resolved;\n }\n\n resolveEditUrl(url: string): string {\n const urlData = parseGitUrl(url);\n const editUrl = new URL(url);\n\n editUrl.searchParams.set('mode', 'edit');\n editUrl.searchParams.set('at', urlData.ref);\n return editUrl.toString();\n }\n}\n"],"names":["config","readBitbucketCloudIntegrationConfigs","basicIntegrations","defaultScmResolveUrl","parseGitUrl"],"mappings":";;;;;;;;;;AA6BO,MAAM,yBAAA,CAAoD;AAAA,EAa/D,YACmB,iBAAA,EACjB;AADiB,IAAA,IAAA,CAAA,iBAAA,GAAA,iBAAA;AAAA,EAChB;AAAA,EADgB,iBAAA;AAAA,EAbnB,OAAO,UAA6D,CAAC;AAAA,YACnEA;AAAA,GACF,KAAM;AACJ,IAAA,MAAM,OAAA,GAAUC,2CAAA;AAAA,MACdD,QAAA,CAAO,sBAAA,CAAuB,6BAA6B,CAAA,IAAK;AAAC,KACnE;AACA,IAAA,OAAOE,yBAAA;AAAA,MACL,QAAQ,GAAA,CAAI,CAAA,CAAA,KAAK,IAAI,yBAAA,CAA0B,CAAC,CAAC,CAAA;AAAA,MACjD,CAAA,CAAA,KAAK,EAAE,MAAA,CAAO;AAAA,KAChB;AAAA,EACF,CAAA;AAAA,EAMA,IAAI,IAAA,GAAe;AACjB,IAAA,OAAO,gBAAA;AAAA,EACT;AAAA,EAEA,IAAI,KAAA,GAAgB;AAClB,IAAA,OAAO,KAAK,iBAAA,CAAkB,IAAA;AAAA,EAChC;AAAA,EAEA,IAAI,MAAA,GAA0C;AAC5C,IAAA,OAAO,IAAA,CAAK,iBAAA;AAAA,EACd;AAAA,EAEA,WAAW,OAAA,EAIA;AACT,IAAA,MAAM,QAAA,GAAWC,6BAAqB,OAAO,CAAA;AAG7C,IAAA,IAAI,QAAQ,UAAA,EAAY;AACtB,MAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,QAAQ,CAAA;AAE5B,MAAA,GAAA,CAAI,IAAA,GAAO,CAAA,MAAA,EAAS,OAAA,CAAQ,UAAU,CAAA,CAAA;AACtC,MAAA,OAAO,IAAI,QAAA,EAAS;AAAA,IACtB;AAEA,IAAA,OAAO,QAAA;AAAA,EACT;AAAA,EAEA,eAAe,GAAA,EAAqB;AAClC,IAAA,MAAM,OAAA,GAAUC,6BAAY,GAAG,CAAA;AAC/B,IAAA,MAAM,OAAA,GAAU,IAAI,GAAA,CAAI,GAAG,CAAA;AAE3B,IAAA,OAAA,CAAQ,YAAA,CAAa,GAAA,CAAI,MAAA,EAAQ,MAAM,CAAA;AACvC,IAAA,OAAA,CAAQ,YAAA,CAAa,GAAA,CAAI,IAAA,EAAM,OAAA,CAAQ,GAAG,CAAA;AAC1C,IAAA,OAAO,QAAQ,QAAA,EAAS;AAAA,EAC1B;AACF;;"}
@@ -6,6 +6,7 @@ class BitbucketCloudIntegration {
6
6
  constructor(integrationConfig) {
7
7
  this.integrationConfig = integrationConfig;
8
8
  }
9
+ integrationConfig;
9
10
  static factory = ({
10
11
  config
11
12
  }) => {
@@ -1 +1 @@
1
- {"version":3,"file":"BitbucketCloudIntegration.esm.js","sources":["../../src/bitbucketCloud/BitbucketCloudIntegration.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 parseGitUrl from 'git-url-parse';\nimport { basicIntegrations, defaultScmResolveUrl } from '../helpers';\nimport { ScmIntegration, ScmIntegrationsFactory } from '../types';\nimport {\n BitbucketCloudIntegrationConfig,\n readBitbucketCloudIntegrationConfigs,\n} from './config';\n\n/**\n * A Bitbucket Cloud based integration.\n *\n * @public\n */\nexport class BitbucketCloudIntegration implements ScmIntegration {\n static factory: ScmIntegrationsFactory<BitbucketCloudIntegration> = ({\n config,\n }) => {\n const configs = readBitbucketCloudIntegrationConfigs(\n config.getOptionalConfigArray('integrations.bitbucketCloud') ?? [],\n );\n return basicIntegrations(\n configs.map(c => new BitbucketCloudIntegration(c)),\n i => i.config.host,\n );\n };\n\n constructor(\n private readonly integrationConfig: BitbucketCloudIntegrationConfig,\n ) {}\n\n get type(): string {\n return 'bitbucketCloud';\n }\n\n get title(): string {\n return this.integrationConfig.host;\n }\n\n get config(): BitbucketCloudIntegrationConfig {\n return this.integrationConfig;\n }\n\n resolveUrl(options: {\n url: string;\n base: string;\n lineNumber?: number;\n }): string {\n const resolved = defaultScmResolveUrl(options);\n\n // Bitbucket Cloud line numbers use the syntax #lines-42, rather than #L42\n if (options.lineNumber) {\n const url = new URL(resolved);\n\n url.hash = `lines-${options.lineNumber}`;\n return url.toString();\n }\n\n return resolved;\n }\n\n resolveEditUrl(url: string): string {\n const urlData = parseGitUrl(url);\n const editUrl = new URL(url);\n\n editUrl.searchParams.set('mode', 'edit');\n editUrl.searchParams.set('at', urlData.ref);\n return editUrl.toString();\n }\n}\n"],"names":[],"mappings":";;;;AA6BO,MAAM,yBAAA,CAAoD;AAAA,EAa/D,YACmB,iBAAA,EACjB;AADiB,IAAA,IAAA,CAAA,iBAAA,GAAA,iBAAA;AAAA,EAChB;AAAA,EAdH,OAAO,UAA6D,CAAC;AAAA,IACnE;AAAA,GACF,KAAM;AACJ,IAAA,MAAM,OAAA,GAAU,oCAAA;AAAA,MACd,MAAA,CAAO,sBAAA,CAAuB,6BAA6B,CAAA,IAAK;AAAC,KACnE;AACA,IAAA,OAAO,iBAAA;AAAA,MACL,QAAQ,GAAA,CAAI,CAAA,CAAA,KAAK,IAAI,yBAAA,CAA0B,CAAC,CAAC,CAAA;AAAA,MACjD,CAAA,CAAA,KAAK,EAAE,MAAA,CAAO;AAAA,KAChB;AAAA,EACF,CAAA;AAAA,EAMA,IAAI,IAAA,GAAe;AACjB,IAAA,OAAO,gBAAA;AAAA,EACT;AAAA,EAEA,IAAI,KAAA,GAAgB;AAClB,IAAA,OAAO,KAAK,iBAAA,CAAkB,IAAA;AAAA,EAChC;AAAA,EAEA,IAAI,MAAA,GAA0C;AAC5C,IAAA,OAAO,IAAA,CAAK,iBAAA;AAAA,EACd;AAAA,EAEA,WAAW,OAAA,EAIA;AACT,IAAA,MAAM,QAAA,GAAW,qBAAqB,OAAO,CAAA;AAG7C,IAAA,IAAI,QAAQ,UAAA,EAAY;AACtB,MAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,QAAQ,CAAA;AAE5B,MAAA,GAAA,CAAI,IAAA,GAAO,CAAA,MAAA,EAAS,OAAA,CAAQ,UAAU,CAAA,CAAA;AACtC,MAAA,OAAO,IAAI,QAAA,EAAS;AAAA,IACtB;AAEA,IAAA,OAAO,QAAA;AAAA,EACT;AAAA,EAEA,eAAe,GAAA,EAAqB;AAClC,IAAA,MAAM,OAAA,GAAU,YAAY,GAAG,CAAA;AAC/B,IAAA,MAAM,OAAA,GAAU,IAAI,GAAA,CAAI,GAAG,CAAA;AAE3B,IAAA,OAAA,CAAQ,YAAA,CAAa,GAAA,CAAI,MAAA,EAAQ,MAAM,CAAA;AACvC,IAAA,OAAA,CAAQ,YAAA,CAAa,GAAA,CAAI,IAAA,EAAM,OAAA,CAAQ,GAAG,CAAA;AAC1C,IAAA,OAAO,QAAQ,QAAA,EAAS;AAAA,EAC1B;AACF;;;;"}
1
+ {"version":3,"file":"BitbucketCloudIntegration.esm.js","sources":["../../src/bitbucketCloud/BitbucketCloudIntegration.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 parseGitUrl from 'git-url-parse';\nimport { basicIntegrations, defaultScmResolveUrl } from '../helpers';\nimport { ScmIntegration, ScmIntegrationsFactory } from '../types';\nimport {\n BitbucketCloudIntegrationConfig,\n readBitbucketCloudIntegrationConfigs,\n} from './config';\n\n/**\n * A Bitbucket Cloud based integration.\n *\n * @public\n */\nexport class BitbucketCloudIntegration implements ScmIntegration {\n static factory: ScmIntegrationsFactory<BitbucketCloudIntegration> = ({\n config,\n }) => {\n const configs = readBitbucketCloudIntegrationConfigs(\n config.getOptionalConfigArray('integrations.bitbucketCloud') ?? [],\n );\n return basicIntegrations(\n configs.map(c => new BitbucketCloudIntegration(c)),\n i => i.config.host,\n );\n };\n\n constructor(\n private readonly integrationConfig: BitbucketCloudIntegrationConfig,\n ) {}\n\n get type(): string {\n return 'bitbucketCloud';\n }\n\n get title(): string {\n return this.integrationConfig.host;\n }\n\n get config(): BitbucketCloudIntegrationConfig {\n return this.integrationConfig;\n }\n\n resolveUrl(options: {\n url: string;\n base: string;\n lineNumber?: number;\n }): string {\n const resolved = defaultScmResolveUrl(options);\n\n // Bitbucket Cloud line numbers use the syntax #lines-42, rather than #L42\n if (options.lineNumber) {\n const url = new URL(resolved);\n\n url.hash = `lines-${options.lineNumber}`;\n return url.toString();\n }\n\n return resolved;\n }\n\n resolveEditUrl(url: string): string {\n const urlData = parseGitUrl(url);\n const editUrl = new URL(url);\n\n editUrl.searchParams.set('mode', 'edit');\n editUrl.searchParams.set('at', urlData.ref);\n return editUrl.toString();\n }\n}\n"],"names":[],"mappings":";;;;AA6BO,MAAM,yBAAA,CAAoD;AAAA,EAa/D,YACmB,iBAAA,EACjB;AADiB,IAAA,IAAA,CAAA,iBAAA,GAAA,iBAAA;AAAA,EAChB;AAAA,EADgB,iBAAA;AAAA,EAbnB,OAAO,UAA6D,CAAC;AAAA,IACnE;AAAA,GACF,KAAM;AACJ,IAAA,MAAM,OAAA,GAAU,oCAAA;AAAA,MACd,MAAA,CAAO,sBAAA,CAAuB,6BAA6B,CAAA,IAAK;AAAC,KACnE;AACA,IAAA,OAAO,iBAAA;AAAA,MACL,QAAQ,GAAA,CAAI,CAAA,CAAA,KAAK,IAAI,yBAAA,CAA0B,CAAC,CAAC,CAAA;AAAA,MACjD,CAAA,CAAA,KAAK,EAAE,MAAA,CAAO;AAAA,KAChB;AAAA,EACF,CAAA;AAAA,EAMA,IAAI,IAAA,GAAe;AACjB,IAAA,OAAO,gBAAA;AAAA,EACT;AAAA,EAEA,IAAI,KAAA,GAAgB;AAClB,IAAA,OAAO,KAAK,iBAAA,CAAkB,IAAA;AAAA,EAChC;AAAA,EAEA,IAAI,MAAA,GAA0C;AAC5C,IAAA,OAAO,IAAA,CAAK,iBAAA;AAAA,EACd;AAAA,EAEA,WAAW,OAAA,EAIA;AACT,IAAA,MAAM,QAAA,GAAW,qBAAqB,OAAO,CAAA;AAG7C,IAAA,IAAI,QAAQ,UAAA,EAAY;AACtB,MAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,QAAQ,CAAA;AAE5B,MAAA,GAAA,CAAI,IAAA,GAAO,CAAA,MAAA,EAAS,OAAA,CAAQ,UAAU,CAAA,CAAA;AACtC,MAAA,OAAO,IAAI,QAAA,EAAS;AAAA,IACtB;AAEA,IAAA,OAAO,QAAA;AAAA,EACT;AAAA,EAEA,eAAe,GAAA,EAAqB;AAClC,IAAA,MAAM,OAAA,GAAU,YAAY,GAAG,CAAA;AAC/B,IAAA,MAAM,OAAA,GAAU,IAAI,GAAA,CAAI,GAAG,CAAA;AAE3B,IAAA,OAAA,CAAQ,YAAA,CAAa,GAAA,CAAI,MAAA,EAAQ,MAAM,CAAA;AACvC,IAAA,OAAA,CAAQ,YAAA,CAAa,GAAA,CAAI,IAAA,EAAM,OAAA,CAAQ,GAAG,CAAA;AAC1C,IAAA,OAAO,QAAQ,QAAA,EAAS;AAAA,EAC1B;AACF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"config.cjs.js","sources":["../../src/bitbucketCloud/config.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 { Config } from '@backstage/config';\n\nconst BITBUCKET_CLOUD_HOST = 'bitbucket.org';\nconst BITBUCKET_CLOUD_API_BASE_URL = 'https://api.bitbucket.org/2.0';\n\n/**\n * The configuration parameters for a single Bitbucket Cloud API provider.\n *\n * @public\n */\nexport type BitbucketCloudIntegrationConfig = {\n /**\n * Constant. bitbucket.org\n */\n host: string;\n\n /**\n * Constant. https://api.bitbucket.org/2.0\n */\n apiBaseUrl: string;\n\n /**\n * The username to use for requests to Bitbucket Cloud (bitbucket.org).\n */\n username?: string;\n\n /**\n * Authentication with Bitbucket Cloud (bitbucket.org) is done using app passwords.\n *\n * See https://support.atlassian.com/bitbucket-cloud/docs/app-passwords/\n */\n appPassword?: string;\n\n /**\n * The access token to use for requests to Bitbucket Cloud (bitbucket.org).\n *\n * See https://support.atlassian.com/bitbucket-cloud/docs/api-tokens/\n */\n token?: string;\n\n /**\n * The OAuth client ID for Bitbucket Cloud.\n *\n * See https://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud/\n */\n clientId?: string;\n\n /**\n * The OAuth client secret for Bitbucket Cloud.\n *\n * See https://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud/\n */\n clientSecret?: string;\n\n /** PGP private key for signing commits. */\n commitSigningKey?: string;\n};\n\n/**\n * Reads a single Bitbucket Cloud integration config.\n *\n * @param config - The config object of a single integration\n * @public\n */\nexport function readBitbucketCloudIntegrationConfig(\n config: Config,\n): BitbucketCloudIntegrationConfig {\n const host = BITBUCKET_CLOUD_HOST;\n const apiBaseUrl = BITBUCKET_CLOUD_API_BASE_URL;\n // If config is provided, we assume authenticated access is desired\n // (as the anonymous one is provided by default).\n const username = config.getOptionalString('username');\n // TODO: appPassword can be removed once fully\n // deprecated by BitBucket on 9th June 2026.\n const appPassword = config.getOptionalString('appPassword')?.trim();\n const token = config.getOptionalString('token');\n const clientId = config.getOptionalString('clientId')?.trim();\n const clientSecret = config.getOptionalString('clientSecret')?.trim();\n\n // Validate: if username is provided, token or appPassword is required\n if (username && !token && !appPassword) {\n throw new Error(\n `Bitbucket Cloud integration must be configured with as username and either a token or an appPassword.`,\n );\n }\n\n // Validate: OAuth requires both clientId and clientSecret\n if ((clientId && !clientSecret) || (clientSecret && !clientId)) {\n throw new Error(\n `Bitbucket Cloud integration has incomplete OAuth configuration. Both clientId and clientSecret are required.`,\n );\n }\n\n return {\n host,\n apiBaseUrl,\n username,\n appPassword,\n token,\n clientId,\n clientSecret,\n commitSigningKey: config.getOptionalString('commitSigningKey'),\n };\n}\n\n/**\n * Reads a set of Bitbucket Cloud integration configs,\n * and inserts one for public Bitbucket Cloud if none specified.\n *\n * @param configs - All of the integration config objects\n * @public\n */\nexport function readBitbucketCloudIntegrationConfigs(\n configs: Config[],\n): BitbucketCloudIntegrationConfig[] {\n // First read all the explicit integrations\n const result = configs.map(readBitbucketCloudIntegrationConfig);\n\n // If no explicit bitbucket.org integration was added,\n // put one in the list as a convenience\n if (result.length === 0) {\n result.push({\n host: BITBUCKET_CLOUD_HOST,\n apiBaseUrl: BITBUCKET_CLOUD_API_BASE_URL,\n });\n }\n\n return result;\n}\n"],"names":[],"mappings":";;AAkBA,MAAM,oBAAA,GAAuB,eAAA;AAC7B,MAAM,4BAAA,GAA+B,+BAAA;AA6D9B,SAAS,oCACd,MAAA,EACiC;AACjC,EAAA,MAAM,IAAA,GAAO,oBAAA;AACb,EAAA,MAAM,UAAA,GAAa,4BAAA;AAGnB,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,iBAAA,CAAkB,UAAU,CAAA;AAGpD,EAAA,MAAM,WAAA,GAAc,MAAA,CAAO,iBAAA,CAAkB,aAAa,GAAG,IAAA,EAAK;AAClE,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,iBAAA,CAAkB,OAAO,CAAA;AAC9C,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,iBAAA,CAAkB,UAAU,GAAG,IAAA,EAAK;AAC5D,EAAA,MAAM,YAAA,GAAe,MAAA,CAAO,iBAAA,CAAkB,cAAc,GAAG,IAAA,EAAK;AAGpE,EAAA,IAAI,QAAA,IAAY,CAAC,KAAA,IAAS,CAAC,WAAA,EAAa;AACtC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,qGAAA;AAAA,KACF;AAAA,EACF;AAGA,EAAA,IAAK,QAAA,IAAY,CAAC,YAAA,IAAkB,YAAA,IAAgB,CAAC,QAAA,EAAW;AAC9D,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,4GAAA;AAAA,KACF;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,IAAA;AAAA,IACA,UAAA;AAAA,IACA,QAAA;AAAA,IACA,WAAA;AAAA,IACA,KAAA;AAAA,IACA,QAAA;AAAA,IACA,YAAA;AAAA,IACA,gBAAA,EAAkB,MAAA,CAAO,iBAAA,CAAkB,kBAAkB;AAAA,GAC/D;AACF;AASO,SAAS,qCACd,OAAA,EACmC;AAEnC,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,GAAA,CAAI,mCAAmC,CAAA;AAI9D,EAAA,IAAI,MAAA,CAAO,WAAW,CAAA,EAAG;AACvB,IAAA,MAAA,CAAO,IAAA,CAAK;AAAA,MACV,IAAA,EAAM,oBAAA;AAAA,MACN,UAAA,EAAY;AAAA,KACb,CAAA;AAAA,EACH;AAEA,EAAA,OAAO,MAAA;AACT;;;;;"}
1
+ {"version":3,"file":"config.cjs.js","sources":["../../src/bitbucketCloud/config.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 { Config } from '@backstage/config';\n\nconst BITBUCKET_CLOUD_HOST = 'bitbucket.org';\nconst BITBUCKET_CLOUD_API_BASE_URL = 'https://api.bitbucket.org/2.0';\n\n/**\n * The configuration parameters for a single Bitbucket Cloud API provider.\n *\n * @public\n */\nexport type BitbucketCloudIntegrationConfig = {\n /**\n * Constant. bitbucket.org\n */\n host: string;\n\n /**\n * Constant. https://api.bitbucket.org/2.0\n */\n apiBaseUrl: string;\n\n /**\n * The username to use for requests to Bitbucket Cloud (bitbucket.org).\n */\n username?: string;\n\n /**\n * Authentication with Bitbucket Cloud (bitbucket.org) is done using app passwords.\n *\n * See https://support.atlassian.com/bitbucket-cloud/docs/app-passwords/\n */\n appPassword?: string;\n\n /**\n * The access token to use for requests to Bitbucket Cloud (bitbucket.org).\n *\n * See https://support.atlassian.com/bitbucket-cloud/docs/api-tokens/\n */\n token?: string;\n\n /**\n * The OAuth client ID for Bitbucket Cloud.\n *\n * See https://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud/\n */\n clientId?: string;\n\n /**\n * The OAuth client secret for Bitbucket Cloud.\n *\n * See https://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud/\n */\n clientSecret?: string;\n\n /** PGP private key for signing commits. */\n commitSigningKey?: string;\n};\n\n/**\n * Reads a single Bitbucket Cloud integration config.\n *\n * @param config - The config object of a single integration\n * @public\n */\nexport function readBitbucketCloudIntegrationConfig(\n config: Config,\n): BitbucketCloudIntegrationConfig {\n const host = BITBUCKET_CLOUD_HOST;\n const apiBaseUrl = BITBUCKET_CLOUD_API_BASE_URL;\n // If config is provided, we assume authenticated access is desired\n // (as the anonymous one is provided by default).\n const username = config.getOptionalString('username');\n // TODO: appPassword can be removed once fully\n // deprecated by BitBucket on 9th June 2026.\n const appPassword = config.getOptionalString('appPassword')?.trim();\n const token = config.getOptionalString('token');\n const clientId = config.getOptionalString('clientId')?.trim();\n const clientSecret = config.getOptionalString('clientSecret')?.trim();\n\n // Validate: if username is provided, token or appPassword is required\n if (username && !token && !appPassword) {\n throw new Error(\n `Bitbucket Cloud integration must be configured with as username and either a token or an appPassword.`,\n );\n }\n\n // Validate: OAuth requires both clientId and clientSecret\n if ((clientId && !clientSecret) || (clientSecret && !clientId)) {\n throw new Error(\n `Bitbucket Cloud integration has incomplete OAuth configuration. Both clientId and clientSecret are required.`,\n );\n }\n\n return {\n host,\n apiBaseUrl,\n username,\n appPassword,\n token,\n clientId,\n clientSecret,\n commitSigningKey: config.getOptionalString('commitSigningKey'),\n };\n}\n\n/**\n * Reads a set of Bitbucket Cloud integration configs,\n * and inserts one for public Bitbucket Cloud if none specified.\n *\n * @param configs - All of the integration config objects\n * @public\n */\nexport function readBitbucketCloudIntegrationConfigs(\n configs: Config[],\n): BitbucketCloudIntegrationConfig[] {\n // First read all the explicit integrations\n const result = configs.map(readBitbucketCloudIntegrationConfig);\n\n // If no explicit bitbucket.org integration was added,\n // put one in the list as a convenience\n if (result.length === 0) {\n result.push({\n host: BITBUCKET_CLOUD_HOST,\n apiBaseUrl: BITBUCKET_CLOUD_API_BASE_URL,\n });\n }\n\n return result;\n}\n"],"names":[],"mappings":";;AAkBA,MAAM,oBAAA,GAAuB,eAAA;AAC7B,MAAM,4BAAA,GAA+B,+BAAA;AA6D9B,SAAS,oCACd,MAAA,EACiC;AACjC,EAAA,MAAM,IAAA,GAAO,oBAAA;AACb,EAAA,MAAM,UAAA,GAAa,4BAAA;AAGnB,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,iBAAA,CAAkB,UAAU,CAAA;AAGpD,EAAA,MAAM,WAAA,GAAc,MAAA,CAAO,iBAAA,CAAkB,aAAa,GAAG,IAAA,EAAK;AAClE,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,iBAAA,CAAkB,OAAO,CAAA;AAC9C,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,iBAAA,CAAkB,UAAU,GAAG,IAAA,EAAK;AAC5D,EAAA,MAAM,YAAA,GAAe,MAAA,CAAO,iBAAA,CAAkB,cAAc,GAAG,IAAA,EAAK;AAGpE,EAAA,IAAI,QAAA,IAAY,CAAC,KAAA,IAAS,CAAC,WAAA,EAAa;AACtC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,qGAAA;AAAA,KACF;AAAA,EACF;AAGA,EAAA,IAAK,QAAA,IAAY,CAAC,YAAA,IAAkB,YAAA,IAAgB,CAAC,QAAA,EAAW;AAC9D,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,4GAAA;AAAA,KACF;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,IAAA;AAAA,IACA,UAAA;AAAA,IACA,QAAA;AAAA,IACA,WAAA;AAAA,IACA,KAAA;AAAA,IACA,QAAA;AAAA,IACA,YAAA;AAAA,IACA,gBAAA,EAAkB,MAAA,CAAO,iBAAA,CAAkB,kBAAkB;AAAA,GAC/D;AACF;AASO,SAAS,qCACd,OAAA,EACmC;AAEnC,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,GAAA,CAAI,mCAAmC,CAAA;AAI9D,EAAA,IAAI,MAAA,CAAO,WAAW,CAAA,EAAG;AACvB,IAAA,MAAA,CAAO,IAAA,CAAK;AAAA,MACV,IAAA,EAAM,oBAAA;AAAA,MACN,UAAA,EAAY;AAAA,KACb,CAAA;AAAA,EACH;AAEA,EAAA,OAAO,MAAA;AACT;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"config.esm.js","sources":["../../src/bitbucketCloud/config.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 { Config } from '@backstage/config';\n\nconst BITBUCKET_CLOUD_HOST = 'bitbucket.org';\nconst BITBUCKET_CLOUD_API_BASE_URL = 'https://api.bitbucket.org/2.0';\n\n/**\n * The configuration parameters for a single Bitbucket Cloud API provider.\n *\n * @public\n */\nexport type BitbucketCloudIntegrationConfig = {\n /**\n * Constant. bitbucket.org\n */\n host: string;\n\n /**\n * Constant. https://api.bitbucket.org/2.0\n */\n apiBaseUrl: string;\n\n /**\n * The username to use for requests to Bitbucket Cloud (bitbucket.org).\n */\n username?: string;\n\n /**\n * Authentication with Bitbucket Cloud (bitbucket.org) is done using app passwords.\n *\n * See https://support.atlassian.com/bitbucket-cloud/docs/app-passwords/\n */\n appPassword?: string;\n\n /**\n * The access token to use for requests to Bitbucket Cloud (bitbucket.org).\n *\n * See https://support.atlassian.com/bitbucket-cloud/docs/api-tokens/\n */\n token?: string;\n\n /**\n * The OAuth client ID for Bitbucket Cloud.\n *\n * See https://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud/\n */\n clientId?: string;\n\n /**\n * The OAuth client secret for Bitbucket Cloud.\n *\n * See https://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud/\n */\n clientSecret?: string;\n\n /** PGP private key for signing commits. */\n commitSigningKey?: string;\n};\n\n/**\n * Reads a single Bitbucket Cloud integration config.\n *\n * @param config - The config object of a single integration\n * @public\n */\nexport function readBitbucketCloudIntegrationConfig(\n config: Config,\n): BitbucketCloudIntegrationConfig {\n const host = BITBUCKET_CLOUD_HOST;\n const apiBaseUrl = BITBUCKET_CLOUD_API_BASE_URL;\n // If config is provided, we assume authenticated access is desired\n // (as the anonymous one is provided by default).\n const username = config.getOptionalString('username');\n // TODO: appPassword can be removed once fully\n // deprecated by BitBucket on 9th June 2026.\n const appPassword = config.getOptionalString('appPassword')?.trim();\n const token = config.getOptionalString('token');\n const clientId = config.getOptionalString('clientId')?.trim();\n const clientSecret = config.getOptionalString('clientSecret')?.trim();\n\n // Validate: if username is provided, token or appPassword is required\n if (username && !token && !appPassword) {\n throw new Error(\n `Bitbucket Cloud integration must be configured with as username and either a token or an appPassword.`,\n );\n }\n\n // Validate: OAuth requires both clientId and clientSecret\n if ((clientId && !clientSecret) || (clientSecret && !clientId)) {\n throw new Error(\n `Bitbucket Cloud integration has incomplete OAuth configuration. Both clientId and clientSecret are required.`,\n );\n }\n\n return {\n host,\n apiBaseUrl,\n username,\n appPassword,\n token,\n clientId,\n clientSecret,\n commitSigningKey: config.getOptionalString('commitSigningKey'),\n };\n}\n\n/**\n * Reads a set of Bitbucket Cloud integration configs,\n * and inserts one for public Bitbucket Cloud if none specified.\n *\n * @param configs - All of the integration config objects\n * @public\n */\nexport function readBitbucketCloudIntegrationConfigs(\n configs: Config[],\n): BitbucketCloudIntegrationConfig[] {\n // First read all the explicit integrations\n const result = configs.map(readBitbucketCloudIntegrationConfig);\n\n // If no explicit bitbucket.org integration was added,\n // put one in the list as a convenience\n if (result.length === 0) {\n result.push({\n host: BITBUCKET_CLOUD_HOST,\n apiBaseUrl: BITBUCKET_CLOUD_API_BASE_URL,\n });\n }\n\n return result;\n}\n"],"names":[],"mappings":"AAkBA,MAAM,oBAAA,GAAuB,eAAA;AAC7B,MAAM,4BAAA,GAA+B,+BAAA;AA6D9B,SAAS,oCACd,MAAA,EACiC;AACjC,EAAA,MAAM,IAAA,GAAO,oBAAA;AACb,EAAA,MAAM,UAAA,GAAa,4BAAA;AAGnB,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,iBAAA,CAAkB,UAAU,CAAA;AAGpD,EAAA,MAAM,WAAA,GAAc,MAAA,CAAO,iBAAA,CAAkB,aAAa,GAAG,IAAA,EAAK;AAClE,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,iBAAA,CAAkB,OAAO,CAAA;AAC9C,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,iBAAA,CAAkB,UAAU,GAAG,IAAA,EAAK;AAC5D,EAAA,MAAM,YAAA,GAAe,MAAA,CAAO,iBAAA,CAAkB,cAAc,GAAG,IAAA,EAAK;AAGpE,EAAA,IAAI,QAAA,IAAY,CAAC,KAAA,IAAS,CAAC,WAAA,EAAa;AACtC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,qGAAA;AAAA,KACF;AAAA,EACF;AAGA,EAAA,IAAK,QAAA,IAAY,CAAC,YAAA,IAAkB,YAAA,IAAgB,CAAC,QAAA,EAAW;AAC9D,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,4GAAA;AAAA,KACF;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,IAAA;AAAA,IACA,UAAA;AAAA,IACA,QAAA;AAAA,IACA,WAAA;AAAA,IACA,KAAA;AAAA,IACA,QAAA;AAAA,IACA,YAAA;AAAA,IACA,gBAAA,EAAkB,MAAA,CAAO,iBAAA,CAAkB,kBAAkB;AAAA,GAC/D;AACF;AASO,SAAS,qCACd,OAAA,EACmC;AAEnC,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,GAAA,CAAI,mCAAmC,CAAA;AAI9D,EAAA,IAAI,MAAA,CAAO,WAAW,CAAA,EAAG;AACvB,IAAA,MAAA,CAAO,IAAA,CAAK;AAAA,MACV,IAAA,EAAM,oBAAA;AAAA,MACN,UAAA,EAAY;AAAA,KACb,CAAA;AAAA,EACH;AAEA,EAAA,OAAO,MAAA;AACT;;;;"}
1
+ {"version":3,"file":"config.esm.js","sources":["../../src/bitbucketCloud/config.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 { Config } from '@backstage/config';\n\nconst BITBUCKET_CLOUD_HOST = 'bitbucket.org';\nconst BITBUCKET_CLOUD_API_BASE_URL = 'https://api.bitbucket.org/2.0';\n\n/**\n * The configuration parameters for a single Bitbucket Cloud API provider.\n *\n * @public\n */\nexport type BitbucketCloudIntegrationConfig = {\n /**\n * Constant. bitbucket.org\n */\n host: string;\n\n /**\n * Constant. https://api.bitbucket.org/2.0\n */\n apiBaseUrl: string;\n\n /**\n * The username to use for requests to Bitbucket Cloud (bitbucket.org).\n */\n username?: string;\n\n /**\n * Authentication with Bitbucket Cloud (bitbucket.org) is done using app passwords.\n *\n * See https://support.atlassian.com/bitbucket-cloud/docs/app-passwords/\n */\n appPassword?: string;\n\n /**\n * The access token to use for requests to Bitbucket Cloud (bitbucket.org).\n *\n * See https://support.atlassian.com/bitbucket-cloud/docs/api-tokens/\n */\n token?: string;\n\n /**\n * The OAuth client ID for Bitbucket Cloud.\n *\n * See https://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud/\n */\n clientId?: string;\n\n /**\n * The OAuth client secret for Bitbucket Cloud.\n *\n * See https://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud/\n */\n clientSecret?: string;\n\n /** PGP private key for signing commits. */\n commitSigningKey?: string;\n};\n\n/**\n * Reads a single Bitbucket Cloud integration config.\n *\n * @param config - The config object of a single integration\n * @public\n */\nexport function readBitbucketCloudIntegrationConfig(\n config: Config,\n): BitbucketCloudIntegrationConfig {\n const host = BITBUCKET_CLOUD_HOST;\n const apiBaseUrl = BITBUCKET_CLOUD_API_BASE_URL;\n // If config is provided, we assume authenticated access is desired\n // (as the anonymous one is provided by default).\n const username = config.getOptionalString('username');\n // TODO: appPassword can be removed once fully\n // deprecated by BitBucket on 9th June 2026.\n const appPassword = config.getOptionalString('appPassword')?.trim();\n const token = config.getOptionalString('token');\n const clientId = config.getOptionalString('clientId')?.trim();\n const clientSecret = config.getOptionalString('clientSecret')?.trim();\n\n // Validate: if username is provided, token or appPassword is required\n if (username && !token && !appPassword) {\n throw new Error(\n `Bitbucket Cloud integration must be configured with as username and either a token or an appPassword.`,\n );\n }\n\n // Validate: OAuth requires both clientId and clientSecret\n if ((clientId && !clientSecret) || (clientSecret && !clientId)) {\n throw new Error(\n `Bitbucket Cloud integration has incomplete OAuth configuration. Both clientId and clientSecret are required.`,\n );\n }\n\n return {\n host,\n apiBaseUrl,\n username,\n appPassword,\n token,\n clientId,\n clientSecret,\n commitSigningKey: config.getOptionalString('commitSigningKey'),\n };\n}\n\n/**\n * Reads a set of Bitbucket Cloud integration configs,\n * and inserts one for public Bitbucket Cloud if none specified.\n *\n * @param configs - All of the integration config objects\n * @public\n */\nexport function readBitbucketCloudIntegrationConfigs(\n configs: Config[],\n): BitbucketCloudIntegrationConfig[] {\n // First read all the explicit integrations\n const result = configs.map(readBitbucketCloudIntegrationConfig);\n\n // If no explicit bitbucket.org integration was added,\n // put one in the list as a convenience\n if (result.length === 0) {\n result.push({\n host: BITBUCKET_CLOUD_HOST,\n apiBaseUrl: BITBUCKET_CLOUD_API_BASE_URL,\n });\n }\n\n return result;\n}\n"],"names":[],"mappings":"AAkBA,MAAM,oBAAA,GAAuB,eAAA;AAC7B,MAAM,4BAAA,GAA+B,+BAAA;AA6D9B,SAAS,oCACd,MAAA,EACiC;AACjC,EAAA,MAAM,IAAA,GAAO,oBAAA;AACb,EAAA,MAAM,UAAA,GAAa,4BAAA;AAGnB,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,iBAAA,CAAkB,UAAU,CAAA;AAGpD,EAAA,MAAM,WAAA,GAAc,MAAA,CAAO,iBAAA,CAAkB,aAAa,GAAG,IAAA,EAAK;AAClE,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,iBAAA,CAAkB,OAAO,CAAA;AAC9C,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,iBAAA,CAAkB,UAAU,GAAG,IAAA,EAAK;AAC5D,EAAA,MAAM,YAAA,GAAe,MAAA,CAAO,iBAAA,CAAkB,cAAc,GAAG,IAAA,EAAK;AAGpE,EAAA,IAAI,QAAA,IAAY,CAAC,KAAA,IAAS,CAAC,WAAA,EAAa;AACtC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,qGAAA;AAAA,KACF;AAAA,EACF;AAGA,EAAA,IAAK,QAAA,IAAY,CAAC,YAAA,IAAkB,YAAA,IAAgB,CAAC,QAAA,EAAW;AAC9D,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,4GAAA;AAAA,KACF;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,IAAA;AAAA,IACA,UAAA;AAAA,IACA,QAAA;AAAA,IACA,WAAA;AAAA,IACA,KAAA;AAAA,IACA,QAAA;AAAA,IACA,YAAA;AAAA,IACA,gBAAA,EAAkB,MAAA,CAAO,iBAAA,CAAkB,kBAAkB;AAAA,GAC/D;AACF;AASO,SAAS,qCACd,OAAA,EACmC;AAEnC,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,GAAA,CAAI,mCAAmC,CAAA;AAI9D,EAAA,IAAI,MAAA,CAAO,WAAW,CAAA,EAAG;AACvB,IAAA,MAAA,CAAO,IAAA,CAAK;AAAA,MACV,IAAA,EAAM,oBAAA;AAAA,MACN,UAAA,EAAY;AAAA,KACb,CAAA;AAAA,EACH;AAEA,EAAA,OAAO,MAAA;AACT;;"}
@@ -10,16 +10,19 @@ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'defau
10
10
  var fetch__default = /*#__PURE__*/_interopDefaultCompat(fetch);
11
11
  var parseGitUrl__default = /*#__PURE__*/_interopDefaultCompat(parseGitUrl);
12
12
 
13
- let cachedToken;
14
- let refreshPromise;
13
+ const tokenCache = /* @__PURE__ */ new Map();
14
+ const refreshPromises = /* @__PURE__ */ new Map();
15
15
  async function getBitbucketCloudOAuthToken(clientId, clientSecret) {
16
- if (cachedToken && luxon.DateTime.now() < cachedToken.expiresAt) {
17
- return cachedToken.token;
16
+ const cacheKey = JSON.stringify([clientId, clientSecret]);
17
+ const cached = tokenCache.get(cacheKey);
18
+ if (cached && luxon.DateTime.now() < cached.expiresAt) {
19
+ return cached.token;
18
20
  }
19
- if (refreshPromise) {
20
- return refreshPromise;
21
+ const inFlight = refreshPromises.get(cacheKey);
22
+ if (inFlight) {
23
+ return inFlight;
21
24
  }
22
- refreshPromise = (async () => {
25
+ const refreshPromise = (async () => {
23
26
  try {
24
27
  const credentials = Buffer.from(
25
28
  `${clientId}:${clientSecret}`,
@@ -47,19 +50,20 @@ async function getBitbucketCloudOAuthToken(clientId, clientSecret) {
47
50
  }
48
51
  const expiresIn = data.expires_in || 3600;
49
52
  const expiresAt = luxon.DateTime.now().plus({ seconds: expiresIn }).minus({ minutes: 10 });
50
- cachedToken = {
53
+ tokenCache.set(cacheKey, {
51
54
  token: data.access_token,
52
55
  expiresAt
53
- };
56
+ });
54
57
  return data.access_token;
55
58
  } catch (error) {
56
59
  throw new Error(
57
60
  `Failed to fetch OAuth token for Bitbucket Cloud: ${error}`
58
61
  );
59
62
  } finally {
60
- refreshPromise = void 0;
63
+ refreshPromises.delete(cacheKey);
61
64
  }
62
65
  })();
66
+ refreshPromises.set(cacheKey, refreshPromise);
63
67
  return refreshPromise;
64
68
  }
65
69
  async function getBitbucketCloudDefaultBranch(url, config) {
@@ -128,6 +132,9 @@ async function getBitbucketCloudRequestOptions(config) {
128
132
  );
129
133
  headers.Authorization = `Basic ${buffer.toString("base64")}`;
130
134
  }
135
+ if (config.token && !config.username) {
136
+ headers.Authorization = `Bearer ${config.token}`;
137
+ }
131
138
  return { headers };
132
139
  }
133
140
 
@@ -1 +1 @@
1
- {"version":3,"file":"core.cjs.js","sources":["../../src/bitbucketCloud/core.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 fetch from 'cross-fetch';\nimport parseGitUrl from 'git-url-parse';\nimport { parseGitUrlSafe } from '../helpers';\nimport { BitbucketCloudIntegrationConfig } from './config';\nimport { DateTime } from 'luxon';\n\ntype OAuthTokenData = {\n token: string;\n expiresAt: DateTime;\n};\n\n// In-memory token cache (single entry since there's only one Bitbucket Cloud integration)\nlet cachedToken: OAuthTokenData | undefined;\n\n// Track in-flight token refresh request to prevent concurrent fetches\nlet refreshPromise: Promise<string> | undefined;\n\n/**\n * Fetches an OAuth access token from Bitbucket Cloud using client credentials flow.\n * Tokens are cached with a 10-minute grace period to account for clock skew.\n * Implements concurrent refresh protection to prevent multiple simultaneous token requests.\n *\n * @param clientId - OAuth client ID\n * @param clientSecret - OAuth client secret\n * @public\n */\nexport async function getBitbucketCloudOAuthToken(\n clientId: string,\n clientSecret: string,\n): Promise<string> {\n // Check cache\n if (cachedToken && DateTime.now() < cachedToken.expiresAt) {\n return cachedToken.token;\n }\n\n // Check if there's already a refresh in progress\n if (refreshPromise) {\n return refreshPromise;\n }\n\n // Start a new token fetch and track it\n refreshPromise = (async () => {\n try {\n // Fetch new token\n const credentials = Buffer.from(\n `${clientId}:${clientSecret}`,\n 'utf8',\n ).toString('base64');\n\n const response = await fetch(\n 'https://bitbucket.org/site/oauth2/access_token',\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n Authorization: `Basic ${credentials}`,\n },\n body: 'grant_type=client_credentials',\n },\n );\n\n if (!response.ok) {\n throw new Error(\n `Failed to fetch OAuth token from Bitbucket Cloud: ${response.status} ${response.statusText}`,\n );\n }\n\n const data = await response.json();\n\n if (!data.access_token) {\n throw new Error('OAuth token response missing access_token field');\n }\n\n // Calculate expiration with 10-minute grace period\n const expiresIn = data.expires_in || 3600; // Default to 1 hour\n const expiresAt = DateTime.now()\n .plus({ seconds: expiresIn })\n .minus({ minutes: 10 });\n\n // Cache the token\n cachedToken = {\n token: data.access_token,\n expiresAt,\n };\n\n return data.access_token;\n } catch (error) {\n throw new Error(\n `Failed to fetch OAuth token for Bitbucket Cloud: ${error}`,\n );\n } finally {\n // Clean up the in-flight promise tracking\n refreshPromise = undefined;\n }\n })();\n\n return refreshPromise;\n}\n\n/**\n * Given a URL pointing to a path on a provider, returns the default branch.\n *\n * @param url - A URL pointing to a path\n * @param config - The relevant provider config\n * @public\n */\nexport async function getBitbucketCloudDefaultBranch(\n url: string,\n config: BitbucketCloudIntegrationConfig,\n): Promise<string> {\n const { name: repoName, owner: project } = parseGitUrl(url);\n\n const branchUrl = `${config.apiBaseUrl}/repositories/${project}/${repoName}`;\n const response = await fetch(\n branchUrl,\n await getBitbucketCloudRequestOptions(config),\n );\n\n if (!response.ok) {\n const message = `Failed to retrieve default branch from ${branchUrl}, ${response.status} ${response.statusText}`;\n throw new Error(message);\n }\n\n const repoInfo = await response.json();\n const defaultBranch = repoInfo.mainbranch.name;\n if (!defaultBranch) {\n throw new Error(\n `Failed to read default branch from ${branchUrl}. ` +\n `Response ${response.status} ${response.json()}`,\n );\n }\n return defaultBranch;\n}\n\n/**\n * Given a URL pointing to a path on a provider, returns a URL that is suitable\n * for downloading the subtree.\n *\n * @param url - A URL pointing to a path\n * @param config - The relevant provider config\n * @public\n */\nexport async function getBitbucketCloudDownloadUrl(\n url: string,\n config: BitbucketCloudIntegrationConfig,\n): Promise<string> {\n const {\n name: repoName,\n owner: project,\n ref,\n protocol,\n resource,\n } = parseGitUrlSafe(url);\n\n let branch = ref;\n if (!branch) {\n branch = await getBitbucketCloudDefaultBranch(url, config);\n }\n return `${protocol}://${resource}/${project}/${repoName}/get/${branch}.tar.gz`;\n}\n\n/**\n * Given a URL pointing to a file on a provider, returns a URL that is suitable\n * for fetching the contents of the data.\n *\n * @remarks\n *\n * Converts\n * from: https://bitbucket.org/orgname/reponame/src/master/file.yaml\n * to: https://api.bitbucket.org/2.0/repositories/orgname/reponame/src/master/file.yaml\n *\n * @param url - A URL pointing to a file\n * @param config - The relevant provider config\n * @public\n */\nexport function getBitbucketCloudFileFetchUrl(\n url: string,\n config: BitbucketCloudIntegrationConfig,\n): string {\n try {\n const { owner, name, ref, filepathtype, filepath } = parseGitUrlSafe(url);\n if (!owner || !name || (filepathtype !== 'src' && filepathtype !== 'raw')) {\n throw new Error('Invalid Bitbucket Cloud URL or file path');\n }\n\n const pathWithoutSlash = filepath.replace(/^\\//, '');\n\n if (!ref) {\n throw new Error('Invalid Bitbucket Cloud URL or file path');\n }\n return `${config.apiBaseUrl}/repositories/${owner}/${name}/src/${ref}/${pathWithoutSlash}`;\n } catch (e) {\n throw new Error(`Incorrect URL: ${url}, ${e}`);\n }\n}\n\n/**\n * Gets the request options necessary to make requests to a given provider.\n * Returns headers for authenticating with Bitbucket Cloud.\n * Supports OAuth (clientId/clientSecret), username/token, and username/appPassword auth.\n *\n * @param config - The relevant provider config\n * @public\n */\nexport async function getBitbucketCloudRequestOptions(\n config: BitbucketCloudIntegrationConfig,\n): Promise<{\n headers: Record<string, string>;\n}> {\n const headers: Record<string, string> = {};\n\n // OAuth authentication (clientId/clientSecret)\n if (config.clientId && config.clientSecret) {\n const token = await getBitbucketCloudOAuthToken(\n config.clientId,\n config.clientSecret,\n );\n headers.Authorization = `Bearer ${token}`;\n return { headers };\n }\n\n // Basic authentication (username + token/appPassword)\n // TODO: appPassword can be removed once fully\n // deprecated by BitBucket on 9th June 2026.\n if (config.username && (config.token ?? config.appPassword)) {\n const buffer = Buffer.from(\n `${config.username}:${config.token ?? config.appPassword}`,\n 'utf8',\n );\n headers.Authorization = `Basic ${buffer.toString('base64')}`;\n }\n\n return { headers };\n}\n"],"names":["DateTime","fetch","parseGitUrl","parseGitUrlSafe"],"mappings":"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"}
1
+ {"version":3,"file":"core.cjs.js","sources":["../../src/bitbucketCloud/core.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 fetch from 'cross-fetch';\nimport parseGitUrl from 'git-url-parse';\nimport { parseGitUrlSafe } from '../helpers';\nimport { BitbucketCloudIntegrationConfig } from './config';\nimport { DateTime } from 'luxon';\n\ntype OAuthTokenData = {\n token: string;\n expiresAt: DateTime;\n};\n\n// In-memory token cache keyed by credentials, so each distinct\n// clientId/clientSecret pair (i.e. each Bitbucket Cloud integration) caches\n// its own token independently.\nconst tokenCache = new Map<string, OAuthTokenData>();\n\n// Track in-flight token refresh requests per credential set to prevent\n// concurrent fetches for the same credentials.\nconst refreshPromises = new Map<string, Promise<string>>();\n\n/**\n * Fetches an OAuth access token from Bitbucket Cloud using client credentials flow.\n * Tokens are cached with a 10-minute grace period to account for clock skew.\n * Implements concurrent refresh protection to prevent multiple simultaneous token requests.\n *\n * @param clientId - OAuth client ID\n * @param clientSecret - OAuth client secret\n * @public\n */\nexport async function getBitbucketCloudOAuthToken(\n clientId: string,\n clientSecret: string,\n): Promise<string> {\n // Derive a cache key from the credentials. Using JSON.stringify of a tuple\n // avoids ambiguity if a clientId contained a delimiter character.\n const cacheKey = JSON.stringify([clientId, clientSecret]);\n\n // Check cache\n const cached = tokenCache.get(cacheKey);\n if (cached && DateTime.now() < cached.expiresAt) {\n return cached.token;\n }\n\n // Check if there's already a refresh in progress for these credentials\n const inFlight = refreshPromises.get(cacheKey);\n if (inFlight) {\n return inFlight;\n }\n\n // Start a new token fetch and track it\n const refreshPromise = (async () => {\n try {\n // Fetch new token\n const credentials = Buffer.from(\n `${clientId}:${clientSecret}`,\n 'utf8',\n ).toString('base64');\n\n const response = await fetch(\n 'https://bitbucket.org/site/oauth2/access_token',\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n Authorization: `Basic ${credentials}`,\n },\n body: 'grant_type=client_credentials',\n },\n );\n\n if (!response.ok) {\n throw new Error(\n `Failed to fetch OAuth token from Bitbucket Cloud: ${response.status} ${response.statusText}`,\n );\n }\n\n const data = await response.json();\n\n if (!data.access_token) {\n throw new Error('OAuth token response missing access_token field');\n }\n\n // Calculate expiration with 10-minute grace period\n const expiresIn = data.expires_in || 3600; // Default to 1 hour\n const expiresAt = DateTime.now()\n .plus({ seconds: expiresIn })\n .minus({ minutes: 10 });\n\n // Cache the token\n tokenCache.set(cacheKey, {\n token: data.access_token,\n expiresAt,\n });\n\n return data.access_token;\n } catch (error) {\n throw new Error(\n `Failed to fetch OAuth token for Bitbucket Cloud: ${error}`,\n );\n } finally {\n // Clean up the in-flight promise tracking for these credentials\n refreshPromises.delete(cacheKey);\n }\n })();\n\n refreshPromises.set(cacheKey, refreshPromise);\n\n return refreshPromise;\n}\n\n/**\n * Given a URL pointing to a path on a provider, returns the default branch.\n *\n * @param url - A URL pointing to a path\n * @param config - The relevant provider config\n * @public\n */\nexport async function getBitbucketCloudDefaultBranch(\n url: string,\n config: BitbucketCloudIntegrationConfig,\n): Promise<string> {\n const { name: repoName, owner: project } = parseGitUrl(url);\n\n const branchUrl = `${config.apiBaseUrl}/repositories/${project}/${repoName}`;\n const response = await fetch(\n branchUrl,\n await getBitbucketCloudRequestOptions(config),\n );\n\n if (!response.ok) {\n const message = `Failed to retrieve default branch from ${branchUrl}, ${response.status} ${response.statusText}`;\n throw new Error(message);\n }\n\n const repoInfo = await response.json();\n const defaultBranch = repoInfo.mainbranch.name;\n if (!defaultBranch) {\n throw new Error(\n `Failed to read default branch from ${branchUrl}. ` +\n `Response ${response.status} ${response.json()}`,\n );\n }\n return defaultBranch;\n}\n\n/**\n * Given a URL pointing to a path on a provider, returns a URL that is suitable\n * for downloading the subtree.\n *\n * @param url - A URL pointing to a path\n * @param config - The relevant provider config\n * @public\n */\nexport async function getBitbucketCloudDownloadUrl(\n url: string,\n config: BitbucketCloudIntegrationConfig,\n): Promise<string> {\n const {\n name: repoName,\n owner: project,\n ref,\n protocol,\n resource,\n } = parseGitUrlSafe(url);\n\n let branch = ref;\n if (!branch) {\n branch = await getBitbucketCloudDefaultBranch(url, config);\n }\n return `${protocol}://${resource}/${project}/${repoName}/get/${branch}.tar.gz`;\n}\n\n/**\n * Given a URL pointing to a file on a provider, returns a URL that is suitable\n * for fetching the contents of the data.\n *\n * @remarks\n *\n * Converts\n * from: https://bitbucket.org/orgname/reponame/src/master/file.yaml\n * to: https://api.bitbucket.org/2.0/repositories/orgname/reponame/src/master/file.yaml\n *\n * @param url - A URL pointing to a file\n * @param config - The relevant provider config\n * @public\n */\nexport function getBitbucketCloudFileFetchUrl(\n url: string,\n config: BitbucketCloudIntegrationConfig,\n): string {\n try {\n const { owner, name, ref, filepathtype, filepath } = parseGitUrlSafe(url);\n if (!owner || !name || (filepathtype !== 'src' && filepathtype !== 'raw')) {\n throw new Error('Invalid Bitbucket Cloud URL or file path');\n }\n\n const pathWithoutSlash = filepath.replace(/^\\//, '');\n\n if (!ref) {\n throw new Error('Invalid Bitbucket Cloud URL or file path');\n }\n return `${config.apiBaseUrl}/repositories/${owner}/${name}/src/${ref}/${pathWithoutSlash}`;\n } catch (e) {\n throw new Error(`Incorrect URL: ${url}, ${e}`);\n }\n}\n\n/**\n * Gets the request options necessary to make requests to a given provider.\n * Returns headers for authenticating with Bitbucket Cloud.\n * Supports OAuth (clientId/clientSecret), username/token, username/appPassword,\n * and Bearer token auth.\n *\n * @param config - The relevant provider config\n * @public\n */\nexport async function getBitbucketCloudRequestOptions(\n config: BitbucketCloudIntegrationConfig,\n): Promise<{\n headers: Record<string, string>;\n}> {\n const headers: Record<string, string> = {};\n\n // OAuth authentication (clientId/clientSecret)\n if (config.clientId && config.clientSecret) {\n const token = await getBitbucketCloudOAuthToken(\n config.clientId,\n config.clientSecret,\n );\n headers.Authorization = `Bearer ${token}`;\n return { headers };\n }\n\n // Basic authentication (username + token/appPassword)\n // TODO: appPassword can be removed once fully\n // deprecated by BitBucket on 9th June 2026.\n if (config.username && (config.token ?? config.appPassword)) {\n const buffer = Buffer.from(\n `${config.username}:${config.token ?? config.appPassword}`,\n 'utf8',\n );\n headers.Authorization = `Basic ${buffer.toString('base64')}`;\n }\n\n // Using Bearer authentication (token only)\n if (config.token && !config.username) {\n headers.Authorization = `Bearer ${config.token}`;\n }\n\n return { headers };\n}\n"],"names":["DateTime","fetch","parseGitUrl","parseGitUrlSafe"],"mappings":"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"}
@@ -3,16 +3,19 @@ import parseGitUrl from 'git-url-parse';
3
3
  import { parseGitUrlSafe } from '../helpers.esm.js';
4
4
  import { DateTime } from 'luxon';
5
5
 
6
- let cachedToken;
7
- let refreshPromise;
6
+ const tokenCache = /* @__PURE__ */ new Map();
7
+ const refreshPromises = /* @__PURE__ */ new Map();
8
8
  async function getBitbucketCloudOAuthToken(clientId, clientSecret) {
9
- if (cachedToken && DateTime.now() < cachedToken.expiresAt) {
10
- return cachedToken.token;
9
+ const cacheKey = JSON.stringify([clientId, clientSecret]);
10
+ const cached = tokenCache.get(cacheKey);
11
+ if (cached && DateTime.now() < cached.expiresAt) {
12
+ return cached.token;
11
13
  }
12
- if (refreshPromise) {
13
- return refreshPromise;
14
+ const inFlight = refreshPromises.get(cacheKey);
15
+ if (inFlight) {
16
+ return inFlight;
14
17
  }
15
- refreshPromise = (async () => {
18
+ const refreshPromise = (async () => {
16
19
  try {
17
20
  const credentials = Buffer.from(
18
21
  `${clientId}:${clientSecret}`,
@@ -40,19 +43,20 @@ async function getBitbucketCloudOAuthToken(clientId, clientSecret) {
40
43
  }
41
44
  const expiresIn = data.expires_in || 3600;
42
45
  const expiresAt = DateTime.now().plus({ seconds: expiresIn }).minus({ minutes: 10 });
43
- cachedToken = {
46
+ tokenCache.set(cacheKey, {
44
47
  token: data.access_token,
45
48
  expiresAt
46
- };
49
+ });
47
50
  return data.access_token;
48
51
  } catch (error) {
49
52
  throw new Error(
50
53
  `Failed to fetch OAuth token for Bitbucket Cloud: ${error}`
51
54
  );
52
55
  } finally {
53
- refreshPromise = void 0;
56
+ refreshPromises.delete(cacheKey);
54
57
  }
55
58
  })();
59
+ refreshPromises.set(cacheKey, refreshPromise);
56
60
  return refreshPromise;
57
61
  }
58
62
  async function getBitbucketCloudDefaultBranch(url, config) {
@@ -121,6 +125,9 @@ async function getBitbucketCloudRequestOptions(config) {
121
125
  );
122
126
  headers.Authorization = `Basic ${buffer.toString("base64")}`;
123
127
  }
128
+ if (config.token && !config.username) {
129
+ headers.Authorization = `Bearer ${config.token}`;
130
+ }
124
131
  return { headers };
125
132
  }
126
133
 
@@ -1 +1 @@
1
- {"version":3,"file":"core.esm.js","sources":["../../src/bitbucketCloud/core.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 fetch from 'cross-fetch';\nimport parseGitUrl from 'git-url-parse';\nimport { parseGitUrlSafe } from '../helpers';\nimport { BitbucketCloudIntegrationConfig } from './config';\nimport { DateTime } from 'luxon';\n\ntype OAuthTokenData = {\n token: string;\n expiresAt: DateTime;\n};\n\n// In-memory token cache (single entry since there's only one Bitbucket Cloud integration)\nlet cachedToken: OAuthTokenData | undefined;\n\n// Track in-flight token refresh request to prevent concurrent fetches\nlet refreshPromise: Promise<string> | undefined;\n\n/**\n * Fetches an OAuth access token from Bitbucket Cloud using client credentials flow.\n * Tokens are cached with a 10-minute grace period to account for clock skew.\n * Implements concurrent refresh protection to prevent multiple simultaneous token requests.\n *\n * @param clientId - OAuth client ID\n * @param clientSecret - OAuth client secret\n * @public\n */\nexport async function getBitbucketCloudOAuthToken(\n clientId: string,\n clientSecret: string,\n): Promise<string> {\n // Check cache\n if (cachedToken && DateTime.now() < cachedToken.expiresAt) {\n return cachedToken.token;\n }\n\n // Check if there's already a refresh in progress\n if (refreshPromise) {\n return refreshPromise;\n }\n\n // Start a new token fetch and track it\n refreshPromise = (async () => {\n try {\n // Fetch new token\n const credentials = Buffer.from(\n `${clientId}:${clientSecret}`,\n 'utf8',\n ).toString('base64');\n\n const response = await fetch(\n 'https://bitbucket.org/site/oauth2/access_token',\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n Authorization: `Basic ${credentials}`,\n },\n body: 'grant_type=client_credentials',\n },\n );\n\n if (!response.ok) {\n throw new Error(\n `Failed to fetch OAuth token from Bitbucket Cloud: ${response.status} ${response.statusText}`,\n );\n }\n\n const data = await response.json();\n\n if (!data.access_token) {\n throw new Error('OAuth token response missing access_token field');\n }\n\n // Calculate expiration with 10-minute grace period\n const expiresIn = data.expires_in || 3600; // Default to 1 hour\n const expiresAt = DateTime.now()\n .plus({ seconds: expiresIn })\n .minus({ minutes: 10 });\n\n // Cache the token\n cachedToken = {\n token: data.access_token,\n expiresAt,\n };\n\n return data.access_token;\n } catch (error) {\n throw new Error(\n `Failed to fetch OAuth token for Bitbucket Cloud: ${error}`,\n );\n } finally {\n // Clean up the in-flight promise tracking\n refreshPromise = undefined;\n }\n })();\n\n return refreshPromise;\n}\n\n/**\n * Given a URL pointing to a path on a provider, returns the default branch.\n *\n * @param url - A URL pointing to a path\n * @param config - The relevant provider config\n * @public\n */\nexport async function getBitbucketCloudDefaultBranch(\n url: string,\n config: BitbucketCloudIntegrationConfig,\n): Promise<string> {\n const { name: repoName, owner: project } = parseGitUrl(url);\n\n const branchUrl = `${config.apiBaseUrl}/repositories/${project}/${repoName}`;\n const response = await fetch(\n branchUrl,\n await getBitbucketCloudRequestOptions(config),\n );\n\n if (!response.ok) {\n const message = `Failed to retrieve default branch from ${branchUrl}, ${response.status} ${response.statusText}`;\n throw new Error(message);\n }\n\n const repoInfo = await response.json();\n const defaultBranch = repoInfo.mainbranch.name;\n if (!defaultBranch) {\n throw new Error(\n `Failed to read default branch from ${branchUrl}. ` +\n `Response ${response.status} ${response.json()}`,\n );\n }\n return defaultBranch;\n}\n\n/**\n * Given a URL pointing to a path on a provider, returns a URL that is suitable\n * for downloading the subtree.\n *\n * @param url - A URL pointing to a path\n * @param config - The relevant provider config\n * @public\n */\nexport async function getBitbucketCloudDownloadUrl(\n url: string,\n config: BitbucketCloudIntegrationConfig,\n): Promise<string> {\n const {\n name: repoName,\n owner: project,\n ref,\n protocol,\n resource,\n } = parseGitUrlSafe(url);\n\n let branch = ref;\n if (!branch) {\n branch = await getBitbucketCloudDefaultBranch(url, config);\n }\n return `${protocol}://${resource}/${project}/${repoName}/get/${branch}.tar.gz`;\n}\n\n/**\n * Given a URL pointing to a file on a provider, returns a URL that is suitable\n * for fetching the contents of the data.\n *\n * @remarks\n *\n * Converts\n * from: https://bitbucket.org/orgname/reponame/src/master/file.yaml\n * to: https://api.bitbucket.org/2.0/repositories/orgname/reponame/src/master/file.yaml\n *\n * @param url - A URL pointing to a file\n * @param config - The relevant provider config\n * @public\n */\nexport function getBitbucketCloudFileFetchUrl(\n url: string,\n config: BitbucketCloudIntegrationConfig,\n): string {\n try {\n const { owner, name, ref, filepathtype, filepath } = parseGitUrlSafe(url);\n if (!owner || !name || (filepathtype !== 'src' && filepathtype !== 'raw')) {\n throw new Error('Invalid Bitbucket Cloud URL or file path');\n }\n\n const pathWithoutSlash = filepath.replace(/^\\//, '');\n\n if (!ref) {\n throw new Error('Invalid Bitbucket Cloud URL or file path');\n }\n return `${config.apiBaseUrl}/repositories/${owner}/${name}/src/${ref}/${pathWithoutSlash}`;\n } catch (e) {\n throw new Error(`Incorrect URL: ${url}, ${e}`);\n }\n}\n\n/**\n * Gets the request options necessary to make requests to a given provider.\n * Returns headers for authenticating with Bitbucket Cloud.\n * Supports OAuth (clientId/clientSecret), username/token, and username/appPassword auth.\n *\n * @param config - The relevant provider config\n * @public\n */\nexport async function getBitbucketCloudRequestOptions(\n config: BitbucketCloudIntegrationConfig,\n): Promise<{\n headers: Record<string, string>;\n}> {\n const headers: Record<string, string> = {};\n\n // OAuth authentication (clientId/clientSecret)\n if (config.clientId && config.clientSecret) {\n const token = await getBitbucketCloudOAuthToken(\n config.clientId,\n config.clientSecret,\n );\n headers.Authorization = `Bearer ${token}`;\n return { headers };\n }\n\n // Basic authentication (username + token/appPassword)\n // TODO: appPassword can be removed once fully\n // deprecated by BitBucket on 9th June 2026.\n if (config.username && (config.token ?? config.appPassword)) {\n const buffer = Buffer.from(\n `${config.username}:${config.token ?? config.appPassword}`,\n 'utf8',\n );\n headers.Authorization = `Basic ${buffer.toString('base64')}`;\n }\n\n return { headers };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"core.esm.js","sources":["../../src/bitbucketCloud/core.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 fetch from 'cross-fetch';\nimport parseGitUrl from 'git-url-parse';\nimport { parseGitUrlSafe } from '../helpers';\nimport { BitbucketCloudIntegrationConfig } from './config';\nimport { DateTime } from 'luxon';\n\ntype OAuthTokenData = {\n token: string;\n expiresAt: DateTime;\n};\n\n// In-memory token cache keyed by credentials, so each distinct\n// clientId/clientSecret pair (i.e. each Bitbucket Cloud integration) caches\n// its own token independently.\nconst tokenCache = new Map<string, OAuthTokenData>();\n\n// Track in-flight token refresh requests per credential set to prevent\n// concurrent fetches for the same credentials.\nconst refreshPromises = new Map<string, Promise<string>>();\n\n/**\n * Fetches an OAuth access token from Bitbucket Cloud using client credentials flow.\n * Tokens are cached with a 10-minute grace period to account for clock skew.\n * Implements concurrent refresh protection to prevent multiple simultaneous token requests.\n *\n * @param clientId - OAuth client ID\n * @param clientSecret - OAuth client secret\n * @public\n */\nexport async function getBitbucketCloudOAuthToken(\n clientId: string,\n clientSecret: string,\n): Promise<string> {\n // Derive a cache key from the credentials. Using JSON.stringify of a tuple\n // avoids ambiguity if a clientId contained a delimiter character.\n const cacheKey = JSON.stringify([clientId, clientSecret]);\n\n // Check cache\n const cached = tokenCache.get(cacheKey);\n if (cached && DateTime.now() < cached.expiresAt) {\n return cached.token;\n }\n\n // Check if there's already a refresh in progress for these credentials\n const inFlight = refreshPromises.get(cacheKey);\n if (inFlight) {\n return inFlight;\n }\n\n // Start a new token fetch and track it\n const refreshPromise = (async () => {\n try {\n // Fetch new token\n const credentials = Buffer.from(\n `${clientId}:${clientSecret}`,\n 'utf8',\n ).toString('base64');\n\n const response = await fetch(\n 'https://bitbucket.org/site/oauth2/access_token',\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n Authorization: `Basic ${credentials}`,\n },\n body: 'grant_type=client_credentials',\n },\n );\n\n if (!response.ok) {\n throw new Error(\n `Failed to fetch OAuth token from Bitbucket Cloud: ${response.status} ${response.statusText}`,\n );\n }\n\n const data = await response.json();\n\n if (!data.access_token) {\n throw new Error('OAuth token response missing access_token field');\n }\n\n // Calculate expiration with 10-minute grace period\n const expiresIn = data.expires_in || 3600; // Default to 1 hour\n const expiresAt = DateTime.now()\n .plus({ seconds: expiresIn })\n .minus({ minutes: 10 });\n\n // Cache the token\n tokenCache.set(cacheKey, {\n token: data.access_token,\n expiresAt,\n });\n\n return data.access_token;\n } catch (error) {\n throw new Error(\n `Failed to fetch OAuth token for Bitbucket Cloud: ${error}`,\n );\n } finally {\n // Clean up the in-flight promise tracking for these credentials\n refreshPromises.delete(cacheKey);\n }\n })();\n\n refreshPromises.set(cacheKey, refreshPromise);\n\n return refreshPromise;\n}\n\n/**\n * Given a URL pointing to a path on a provider, returns the default branch.\n *\n * @param url - A URL pointing to a path\n * @param config - The relevant provider config\n * @public\n */\nexport async function getBitbucketCloudDefaultBranch(\n url: string,\n config: BitbucketCloudIntegrationConfig,\n): Promise<string> {\n const { name: repoName, owner: project } = parseGitUrl(url);\n\n const branchUrl = `${config.apiBaseUrl}/repositories/${project}/${repoName}`;\n const response = await fetch(\n branchUrl,\n await getBitbucketCloudRequestOptions(config),\n );\n\n if (!response.ok) {\n const message = `Failed to retrieve default branch from ${branchUrl}, ${response.status} ${response.statusText}`;\n throw new Error(message);\n }\n\n const repoInfo = await response.json();\n const defaultBranch = repoInfo.mainbranch.name;\n if (!defaultBranch) {\n throw new Error(\n `Failed to read default branch from ${branchUrl}. ` +\n `Response ${response.status} ${response.json()}`,\n );\n }\n return defaultBranch;\n}\n\n/**\n * Given a URL pointing to a path on a provider, returns a URL that is suitable\n * for downloading the subtree.\n *\n * @param url - A URL pointing to a path\n * @param config - The relevant provider config\n * @public\n */\nexport async function getBitbucketCloudDownloadUrl(\n url: string,\n config: BitbucketCloudIntegrationConfig,\n): Promise<string> {\n const {\n name: repoName,\n owner: project,\n ref,\n protocol,\n resource,\n } = parseGitUrlSafe(url);\n\n let branch = ref;\n if (!branch) {\n branch = await getBitbucketCloudDefaultBranch(url, config);\n }\n return `${protocol}://${resource}/${project}/${repoName}/get/${branch}.tar.gz`;\n}\n\n/**\n * Given a URL pointing to a file on a provider, returns a URL that is suitable\n * for fetching the contents of the data.\n *\n * @remarks\n *\n * Converts\n * from: https://bitbucket.org/orgname/reponame/src/master/file.yaml\n * to: https://api.bitbucket.org/2.0/repositories/orgname/reponame/src/master/file.yaml\n *\n * @param url - A URL pointing to a file\n * @param config - The relevant provider config\n * @public\n */\nexport function getBitbucketCloudFileFetchUrl(\n url: string,\n config: BitbucketCloudIntegrationConfig,\n): string {\n try {\n const { owner, name, ref, filepathtype, filepath } = parseGitUrlSafe(url);\n if (!owner || !name || (filepathtype !== 'src' && filepathtype !== 'raw')) {\n throw new Error('Invalid Bitbucket Cloud URL or file path');\n }\n\n const pathWithoutSlash = filepath.replace(/^\\//, '');\n\n if (!ref) {\n throw new Error('Invalid Bitbucket Cloud URL or file path');\n }\n return `${config.apiBaseUrl}/repositories/${owner}/${name}/src/${ref}/${pathWithoutSlash}`;\n } catch (e) {\n throw new Error(`Incorrect URL: ${url}, ${e}`);\n }\n}\n\n/**\n * Gets the request options necessary to make requests to a given provider.\n * Returns headers for authenticating with Bitbucket Cloud.\n * Supports OAuth (clientId/clientSecret), username/token, username/appPassword,\n * and Bearer token auth.\n *\n * @param config - The relevant provider config\n * @public\n */\nexport async function getBitbucketCloudRequestOptions(\n config: BitbucketCloudIntegrationConfig,\n): Promise<{\n headers: Record<string, string>;\n}> {\n const headers: Record<string, string> = {};\n\n // OAuth authentication (clientId/clientSecret)\n if (config.clientId && config.clientSecret) {\n const token = await getBitbucketCloudOAuthToken(\n config.clientId,\n config.clientSecret,\n );\n headers.Authorization = `Bearer ${token}`;\n return { headers };\n }\n\n // Basic authentication (username + token/appPassword)\n // TODO: appPassword can be removed once fully\n // deprecated by BitBucket on 9th June 2026.\n if (config.username && (config.token ?? config.appPassword)) {\n const buffer = Buffer.from(\n `${config.username}:${config.token ?? config.appPassword}`,\n 'utf8',\n );\n headers.Authorization = `Basic ${buffer.toString('base64')}`;\n }\n\n // Using Bearer authentication (token only)\n if (config.token && !config.username) {\n headers.Authorization = `Bearer ${config.token}`;\n }\n\n return { headers };\n}\n"],"names":[],"mappings":"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"}
@@ -7,6 +7,7 @@ class BitbucketServerIntegration {
7
7
  constructor(integrationConfig) {
8
8
  this.integrationConfig = integrationConfig;
9
9
  }
10
+ integrationConfig;
10
11
  static factory = ({
11
12
  config: config$1
12
13
  }) => {
@@ -1 +1 @@
1
- {"version":3,"file":"BitbucketServerIntegration.cjs.js","sources":["../../src/bitbucketServer/BitbucketServerIntegration.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 { basicIntegrations, defaultScmResolveUrl } from '../helpers';\nimport { ScmIntegration, ScmIntegrationsFactory } from '../types';\nimport {\n BitbucketServerIntegrationConfig,\n readBitbucketServerIntegrationConfigs,\n} from './config';\n\n/**\n * A Bitbucket Server based integration.\n *\n * @public\n */\nexport class BitbucketServerIntegration implements ScmIntegration {\n static factory: ScmIntegrationsFactory<BitbucketServerIntegration> = ({\n config,\n }) => {\n const configs = readBitbucketServerIntegrationConfigs(\n config.getOptionalConfigArray('integrations.bitbucketServer') ?? [],\n );\n return basicIntegrations(\n configs.map(c => new BitbucketServerIntegration(c)),\n i => i.config.host,\n );\n };\n\n constructor(\n private readonly integrationConfig: BitbucketServerIntegrationConfig,\n ) {}\n\n get type(): string {\n return 'bitbucketServer';\n }\n\n get title(): string {\n return this.integrationConfig.host;\n }\n\n get config(): BitbucketServerIntegrationConfig {\n return this.integrationConfig;\n }\n\n resolveUrl(options: {\n url: string;\n base: string;\n lineNumber?: number;\n }): string {\n const resolved = defaultScmResolveUrl(options);\n\n // Bitbucket Server line numbers use the syntax #42, rather than #L42\n if (options.lineNumber) {\n const url = new URL(resolved);\n\n url.hash = options.lineNumber.toString();\n return url.toString();\n }\n\n return resolved;\n }\n\n resolveEditUrl(url: string): string {\n // Bitbucket Server doesn't support deep linking to edit mode, therefore there's nothing to do here.\n // We just remove query parameters since they cause issues with TechDocs edit button.\n if (url.includes('?')) {\n return url.substring(0, url.indexOf('?'));\n }\n return url;\n }\n}\n"],"names":["config","readBitbucketServerIntegrationConfigs","basicIntegrations","defaultScmResolveUrl"],"mappings":";;;;;AA4BO,MAAM,0BAAA,CAAqD;AAAA,EAahE,YACmB,iBAAA,EACjB;AADiB,IAAA,IAAA,CAAA,iBAAA,GAAA,iBAAA;AAAA,EAChB;AAAA,EAdH,OAAO,UAA8D,CAAC;AAAA,YACpEA;AAAA,GACF,KAAM;AACJ,IAAA,MAAM,OAAA,GAAUC,4CAAA;AAAA,MACdD,QAAA,CAAO,sBAAA,CAAuB,8BAA8B,CAAA,IAAK;AAAC,KACpE;AACA,IAAA,OAAOE,yBAAA;AAAA,MACL,QAAQ,GAAA,CAAI,CAAA,CAAA,KAAK,IAAI,0BAAA,CAA2B,CAAC,CAAC,CAAA;AAAA,MAClD,CAAA,CAAA,KAAK,EAAE,MAAA,CAAO;AAAA,KAChB;AAAA,EACF,CAAA;AAAA,EAMA,IAAI,IAAA,GAAe;AACjB,IAAA,OAAO,iBAAA;AAAA,EACT;AAAA,EAEA,IAAI,KAAA,GAAgB;AAClB,IAAA,OAAO,KAAK,iBAAA,CAAkB,IAAA;AAAA,EAChC;AAAA,EAEA,IAAI,MAAA,GAA2C;AAC7C,IAAA,OAAO,IAAA,CAAK,iBAAA;AAAA,EACd;AAAA,EAEA,WAAW,OAAA,EAIA;AACT,IAAA,MAAM,QAAA,GAAWC,6BAAqB,OAAO,CAAA;AAG7C,IAAA,IAAI,QAAQ,UAAA,EAAY;AACtB,MAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,QAAQ,CAAA;AAE5B,MAAA,GAAA,CAAI,IAAA,GAAO,OAAA,CAAQ,UAAA,CAAW,QAAA,EAAS;AACvC,MAAA,OAAO,IAAI,QAAA,EAAS;AAAA,IACtB;AAEA,IAAA,OAAO,QAAA;AAAA,EACT;AAAA,EAEA,eAAe,GAAA,EAAqB;AAGlC,IAAA,IAAI,GAAA,CAAI,QAAA,CAAS,GAAG,CAAA,EAAG;AACrB,MAAA,OAAO,IAAI,SAAA,CAAU,CAAA,EAAG,GAAA,CAAI,OAAA,CAAQ,GAAG,CAAC,CAAA;AAAA,IAC1C;AACA,IAAA,OAAO,GAAA;AAAA,EACT;AACF;;;;"}
1
+ {"version":3,"file":"BitbucketServerIntegration.cjs.js","sources":["../../src/bitbucketServer/BitbucketServerIntegration.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 { basicIntegrations, defaultScmResolveUrl } from '../helpers';\nimport { ScmIntegration, ScmIntegrationsFactory } from '../types';\nimport {\n BitbucketServerIntegrationConfig,\n readBitbucketServerIntegrationConfigs,\n} from './config';\n\n/**\n * A Bitbucket Server based integration.\n *\n * @public\n */\nexport class BitbucketServerIntegration implements ScmIntegration {\n static factory: ScmIntegrationsFactory<BitbucketServerIntegration> = ({\n config,\n }) => {\n const configs = readBitbucketServerIntegrationConfigs(\n config.getOptionalConfigArray('integrations.bitbucketServer') ?? [],\n );\n return basicIntegrations(\n configs.map(c => new BitbucketServerIntegration(c)),\n i => i.config.host,\n );\n };\n\n constructor(\n private readonly integrationConfig: BitbucketServerIntegrationConfig,\n ) {}\n\n get type(): string {\n return 'bitbucketServer';\n }\n\n get title(): string {\n return this.integrationConfig.host;\n }\n\n get config(): BitbucketServerIntegrationConfig {\n return this.integrationConfig;\n }\n\n resolveUrl(options: {\n url: string;\n base: string;\n lineNumber?: number;\n }): string {\n const resolved = defaultScmResolveUrl(options);\n\n // Bitbucket Server line numbers use the syntax #42, rather than #L42\n if (options.lineNumber) {\n const url = new URL(resolved);\n\n url.hash = options.lineNumber.toString();\n return url.toString();\n }\n\n return resolved;\n }\n\n resolveEditUrl(url: string): string {\n // Bitbucket Server doesn't support deep linking to edit mode, therefore there's nothing to do here.\n // We just remove query parameters since they cause issues with TechDocs edit button.\n if (url.includes('?')) {\n return url.substring(0, url.indexOf('?'));\n }\n return url;\n }\n}\n"],"names":["config","readBitbucketServerIntegrationConfigs","basicIntegrations","defaultScmResolveUrl"],"mappings":";;;;;AA4BO,MAAM,0BAAA,CAAqD;AAAA,EAahE,YACmB,iBAAA,EACjB;AADiB,IAAA,IAAA,CAAA,iBAAA,GAAA,iBAAA;AAAA,EAChB;AAAA,EADgB,iBAAA;AAAA,EAbnB,OAAO,UAA8D,CAAC;AAAA,YACpEA;AAAA,GACF,KAAM;AACJ,IAAA,MAAM,OAAA,GAAUC,4CAAA;AAAA,MACdD,QAAA,CAAO,sBAAA,CAAuB,8BAA8B,CAAA,IAAK;AAAC,KACpE;AACA,IAAA,OAAOE,yBAAA;AAAA,MACL,QAAQ,GAAA,CAAI,CAAA,CAAA,KAAK,IAAI,0BAAA,CAA2B,CAAC,CAAC,CAAA;AAAA,MAClD,CAAA,CAAA,KAAK,EAAE,MAAA,CAAO;AAAA,KAChB;AAAA,EACF,CAAA;AAAA,EAMA,IAAI,IAAA,GAAe;AACjB,IAAA,OAAO,iBAAA;AAAA,EACT;AAAA,EAEA,IAAI,KAAA,GAAgB;AAClB,IAAA,OAAO,KAAK,iBAAA,CAAkB,IAAA;AAAA,EAChC;AAAA,EAEA,IAAI,MAAA,GAA2C;AAC7C,IAAA,OAAO,IAAA,CAAK,iBAAA;AAAA,EACd;AAAA,EAEA,WAAW,OAAA,EAIA;AACT,IAAA,MAAM,QAAA,GAAWC,6BAAqB,OAAO,CAAA;AAG7C,IAAA,IAAI,QAAQ,UAAA,EAAY;AACtB,MAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,QAAQ,CAAA;AAE5B,MAAA,GAAA,CAAI,IAAA,GAAO,OAAA,CAAQ,UAAA,CAAW,QAAA,EAAS;AACvC,MAAA,OAAO,IAAI,QAAA,EAAS;AAAA,IACtB;AAEA,IAAA,OAAO,QAAA;AAAA,EACT;AAAA,EAEA,eAAe,GAAA,EAAqB;AAGlC,IAAA,IAAI,GAAA,CAAI,QAAA,CAAS,GAAG,CAAA,EAAG;AACrB,MAAA,OAAO,IAAI,SAAA,CAAU,CAAA,EAAG,GAAA,CAAI,OAAA,CAAQ,GAAG,CAAC,CAAA;AAAA,IAC1C;AACA,IAAA,OAAO,GAAA;AAAA,EACT;AACF;;"}
@@ -5,6 +5,7 @@ class BitbucketServerIntegration {
5
5
  constructor(integrationConfig) {
6
6
  this.integrationConfig = integrationConfig;
7
7
  }
8
+ integrationConfig;
8
9
  static factory = ({
9
10
  config
10
11
  }) => {
@@ -1 +1 @@
1
- {"version":3,"file":"BitbucketServerIntegration.esm.js","sources":["../../src/bitbucketServer/BitbucketServerIntegration.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 { basicIntegrations, defaultScmResolveUrl } from '../helpers';\nimport { ScmIntegration, ScmIntegrationsFactory } from '../types';\nimport {\n BitbucketServerIntegrationConfig,\n readBitbucketServerIntegrationConfigs,\n} from './config';\n\n/**\n * A Bitbucket Server based integration.\n *\n * @public\n */\nexport class BitbucketServerIntegration implements ScmIntegration {\n static factory: ScmIntegrationsFactory<BitbucketServerIntegration> = ({\n config,\n }) => {\n const configs = readBitbucketServerIntegrationConfigs(\n config.getOptionalConfigArray('integrations.bitbucketServer') ?? [],\n );\n return basicIntegrations(\n configs.map(c => new BitbucketServerIntegration(c)),\n i => i.config.host,\n );\n };\n\n constructor(\n private readonly integrationConfig: BitbucketServerIntegrationConfig,\n ) {}\n\n get type(): string {\n return 'bitbucketServer';\n }\n\n get title(): string {\n return this.integrationConfig.host;\n }\n\n get config(): BitbucketServerIntegrationConfig {\n return this.integrationConfig;\n }\n\n resolveUrl(options: {\n url: string;\n base: string;\n lineNumber?: number;\n }): string {\n const resolved = defaultScmResolveUrl(options);\n\n // Bitbucket Server line numbers use the syntax #42, rather than #L42\n if (options.lineNumber) {\n const url = new URL(resolved);\n\n url.hash = options.lineNumber.toString();\n return url.toString();\n }\n\n return resolved;\n }\n\n resolveEditUrl(url: string): string {\n // Bitbucket Server doesn't support deep linking to edit mode, therefore there's nothing to do here.\n // We just remove query parameters since they cause issues with TechDocs edit button.\n if (url.includes('?')) {\n return url.substring(0, url.indexOf('?'));\n }\n return url;\n }\n}\n"],"names":[],"mappings":";;;AA4BO,MAAM,0BAAA,CAAqD;AAAA,EAahE,YACmB,iBAAA,EACjB;AADiB,IAAA,IAAA,CAAA,iBAAA,GAAA,iBAAA;AAAA,EAChB;AAAA,EAdH,OAAO,UAA8D,CAAC;AAAA,IACpE;AAAA,GACF,KAAM;AACJ,IAAA,MAAM,OAAA,GAAU,qCAAA;AAAA,MACd,MAAA,CAAO,sBAAA,CAAuB,8BAA8B,CAAA,IAAK;AAAC,KACpE;AACA,IAAA,OAAO,iBAAA;AAAA,MACL,QAAQ,GAAA,CAAI,CAAA,CAAA,KAAK,IAAI,0BAAA,CAA2B,CAAC,CAAC,CAAA;AAAA,MAClD,CAAA,CAAA,KAAK,EAAE,MAAA,CAAO;AAAA,KAChB;AAAA,EACF,CAAA;AAAA,EAMA,IAAI,IAAA,GAAe;AACjB,IAAA,OAAO,iBAAA;AAAA,EACT;AAAA,EAEA,IAAI,KAAA,GAAgB;AAClB,IAAA,OAAO,KAAK,iBAAA,CAAkB,IAAA;AAAA,EAChC;AAAA,EAEA,IAAI,MAAA,GAA2C;AAC7C,IAAA,OAAO,IAAA,CAAK,iBAAA;AAAA,EACd;AAAA,EAEA,WAAW,OAAA,EAIA;AACT,IAAA,MAAM,QAAA,GAAW,qBAAqB,OAAO,CAAA;AAG7C,IAAA,IAAI,QAAQ,UAAA,EAAY;AACtB,MAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,QAAQ,CAAA;AAE5B,MAAA,GAAA,CAAI,IAAA,GAAO,OAAA,CAAQ,UAAA,CAAW,QAAA,EAAS;AACvC,MAAA,OAAO,IAAI,QAAA,EAAS;AAAA,IACtB;AAEA,IAAA,OAAO,QAAA;AAAA,EACT;AAAA,EAEA,eAAe,GAAA,EAAqB;AAGlC,IAAA,IAAI,GAAA,CAAI,QAAA,CAAS,GAAG,CAAA,EAAG;AACrB,MAAA,OAAO,IAAI,SAAA,CAAU,CAAA,EAAG,GAAA,CAAI,OAAA,CAAQ,GAAG,CAAC,CAAA;AAAA,IAC1C;AACA,IAAA,OAAO,GAAA;AAAA,EACT;AACF;;;;"}
1
+ {"version":3,"file":"BitbucketServerIntegration.esm.js","sources":["../../src/bitbucketServer/BitbucketServerIntegration.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 { basicIntegrations, defaultScmResolveUrl } from '../helpers';\nimport { ScmIntegration, ScmIntegrationsFactory } from '../types';\nimport {\n BitbucketServerIntegrationConfig,\n readBitbucketServerIntegrationConfigs,\n} from './config';\n\n/**\n * A Bitbucket Server based integration.\n *\n * @public\n */\nexport class BitbucketServerIntegration implements ScmIntegration {\n static factory: ScmIntegrationsFactory<BitbucketServerIntegration> = ({\n config,\n }) => {\n const configs = readBitbucketServerIntegrationConfigs(\n config.getOptionalConfigArray('integrations.bitbucketServer') ?? [],\n );\n return basicIntegrations(\n configs.map(c => new BitbucketServerIntegration(c)),\n i => i.config.host,\n );\n };\n\n constructor(\n private readonly integrationConfig: BitbucketServerIntegrationConfig,\n ) {}\n\n get type(): string {\n return 'bitbucketServer';\n }\n\n get title(): string {\n return this.integrationConfig.host;\n }\n\n get config(): BitbucketServerIntegrationConfig {\n return this.integrationConfig;\n }\n\n resolveUrl(options: {\n url: string;\n base: string;\n lineNumber?: number;\n }): string {\n const resolved = defaultScmResolveUrl(options);\n\n // Bitbucket Server line numbers use the syntax #42, rather than #L42\n if (options.lineNumber) {\n const url = new URL(resolved);\n\n url.hash = options.lineNumber.toString();\n return url.toString();\n }\n\n return resolved;\n }\n\n resolveEditUrl(url: string): string {\n // Bitbucket Server doesn't support deep linking to edit mode, therefore there's nothing to do here.\n // We just remove query parameters since they cause issues with TechDocs edit button.\n if (url.includes('?')) {\n return url.substring(0, url.indexOf('?'));\n }\n return url;\n }\n}\n"],"names":[],"mappings":";;;AA4BO,MAAM,0BAAA,CAAqD;AAAA,EAahE,YACmB,iBAAA,EACjB;AADiB,IAAA,IAAA,CAAA,iBAAA,GAAA,iBAAA;AAAA,EAChB;AAAA,EADgB,iBAAA;AAAA,EAbnB,OAAO,UAA8D,CAAC;AAAA,IACpE;AAAA,GACF,KAAM;AACJ,IAAA,MAAM,OAAA,GAAU,qCAAA;AAAA,MACd,MAAA,CAAO,sBAAA,CAAuB,8BAA8B,CAAA,IAAK;AAAC,KACpE;AACA,IAAA,OAAO,iBAAA;AAAA,MACL,QAAQ,GAAA,CAAI,CAAA,CAAA,KAAK,IAAI,0BAAA,CAA2B,CAAC,CAAC,CAAA;AAAA,MAClD,CAAA,CAAA,KAAK,EAAE,MAAA,CAAO;AAAA,KAChB;AAAA,EACF,CAAA;AAAA,EAMA,IAAI,IAAA,GAAe;AACjB,IAAA,OAAO,iBAAA;AAAA,EACT;AAAA,EAEA,IAAI,KAAA,GAAgB;AAClB,IAAA,OAAO,KAAK,iBAAA,CAAkB,IAAA;AAAA,EAChC;AAAA,EAEA,IAAI,MAAA,GAA2C;AAC7C,IAAA,OAAO,IAAA,CAAK,iBAAA;AAAA,EACd;AAAA,EAEA,WAAW,OAAA,EAIA;AACT,IAAA,MAAM,QAAA,GAAW,qBAAqB,OAAO,CAAA;AAG7C,IAAA,IAAI,QAAQ,UAAA,EAAY;AACtB,MAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,QAAQ,CAAA;AAE5B,MAAA,GAAA,CAAI,IAAA,GAAO,OAAA,CAAQ,UAAA,CAAW,QAAA,EAAS;AACvC,MAAA,OAAO,IAAI,QAAA,EAAS;AAAA,IACtB;AAEA,IAAA,OAAO,QAAA;AAAA,EACT;AAAA,EAEA,eAAe,GAAA,EAAqB;AAGlC,IAAA,IAAI,GAAA,CAAI,QAAA,CAAS,GAAG,CAAA,EAAG;AACrB,MAAA,OAAO,IAAI,SAAA,CAAU,CAAA,EAAG,GAAA,CAAI,OAAA,CAAQ,GAAG,CAAC,CAAA;AAAA,IAC1C;AACA,IAAA,OAAO,GAAA;AAAA,EACT;AACF;;"}