@backstage/plugin-techdocs-node 1.13.2-next.1 → 1.13.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
# @backstage/plugin-techdocs-node
|
|
2
2
|
|
|
3
|
+
## 1.13.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 304a422: Update AWS file retrieval logic from storing file in buffer array to piping to res for better memory efficiency.
|
|
8
|
+
- 2d7a3b8: Update Azure file retrieval logic from storing file in buffer array to piping to res for better memory efficiency.
|
|
9
|
+
- Updated dependencies
|
|
10
|
+
- @backstage/backend-plugin-api@1.3.0
|
|
11
|
+
- @backstage/integration@1.16.3
|
|
12
|
+
- @backstage/catalog-model@1.7.3
|
|
13
|
+
- @backstage/config@1.3.2
|
|
14
|
+
- @backstage/errors@1.2.7
|
|
15
|
+
- @backstage/integration-aws-node@0.1.15
|
|
16
|
+
- @backstage/plugin-search-common@1.2.17
|
|
17
|
+
- @backstage/plugin-techdocs-common@0.1.0
|
|
18
|
+
|
|
19
|
+
## 1.13.2-next.2
|
|
20
|
+
|
|
21
|
+
### Patch Changes
|
|
22
|
+
|
|
23
|
+
- 2d7a3b8: Update Azure file retrieval logic from storing file in buffer array to piping to res for better memory efficiency.
|
|
24
|
+
- Updated dependencies
|
|
25
|
+
- @backstage/backend-plugin-api@1.2.1
|
|
26
|
+
- @backstage/catalog-model@1.7.3
|
|
27
|
+
- @backstage/config@1.3.2
|
|
28
|
+
- @backstage/errors@1.2.7
|
|
29
|
+
- @backstage/integration@1.16.3-next.0
|
|
30
|
+
- @backstage/integration-aws-node@0.1.15
|
|
31
|
+
- @backstage/plugin-search-common@1.2.17
|
|
32
|
+
- @backstage/plugin-techdocs-common@0.1.0
|
|
33
|
+
|
|
3
34
|
## 1.13.2-next.1
|
|
4
35
|
|
|
5
36
|
### Patch Changes
|
|
@@ -197,30 +197,26 @@ class AzureBlobStoragePublish {
|
|
|
197
197
|
}
|
|
198
198
|
return { objects };
|
|
199
199
|
}
|
|
200
|
-
download(containerName, blobPath) {
|
|
201
|
-
return new Promise((resolve, reject) => {
|
|
202
|
-
const fileStreamChunks = [];
|
|
203
|
-
this.storageClient.getContainerClient(containerName).getBlockBlobClient(blobPath).download().then((res) => {
|
|
204
|
-
const body = res.readableStreamBody;
|
|
205
|
-
if (!body) {
|
|
206
|
-
reject(new Error(`Unable to parse the response data`));
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
209
|
-
body.on("error", reject).on("data", (chunk) => {
|
|
210
|
-
fileStreamChunks.push(chunk);
|
|
211
|
-
}).on("end", () => {
|
|
212
|
-
resolve(Buffer.concat(fileStreamChunks));
|
|
213
|
-
});
|
|
214
|
-
}).catch(reject);
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
200
|
async fetchTechDocsMetadata(entityName) {
|
|
218
201
|
const entityTriplet = `${entityName.namespace}/${entityName.kind}/${entityName.name}`;
|
|
219
202
|
const entityRootDir = this.legacyPathCasing ? entityTriplet : helpers.lowerCaseEntityTriplet(entityTriplet);
|
|
220
203
|
try {
|
|
221
|
-
const techdocsMetadataJson = await
|
|
222
|
-
|
|
223
|
-
|
|
204
|
+
const techdocsMetadataJson = await new Promise(
|
|
205
|
+
(resolve, reject) => {
|
|
206
|
+
const fileStreamChunks = [];
|
|
207
|
+
this.storageClient.getContainerClient(this.containerName).getBlockBlobClient(`${entityRootDir}/techdocs_metadata.json`).download().then((res) => {
|
|
208
|
+
const body = res.readableStreamBody;
|
|
209
|
+
if (!body) {
|
|
210
|
+
reject(new Error(`Unable to parse the response data`));
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
body.on("error", reject).on("data", (chunk) => {
|
|
214
|
+
fileStreamChunks.push(chunk);
|
|
215
|
+
}).on("end", () => {
|
|
216
|
+
resolve(Buffer.concat(fileStreamChunks));
|
|
217
|
+
});
|
|
218
|
+
}).catch(reject);
|
|
219
|
+
}
|
|
224
220
|
);
|
|
225
221
|
if (!techdocsMetadataJson) {
|
|
226
222
|
throw new Error(
|
|
@@ -244,18 +240,26 @@ class AzureBlobStoragePublish {
|
|
|
244
240
|
const filePath = this.legacyPathCasing ? decodedUri : helpers.lowerCaseEntityTripletInStoragePath(decodedUri);
|
|
245
241
|
const fileExtension = path__default.default.extname(filePath);
|
|
246
242
|
const responseHeaders = helpers.getHeadersForFileExtension(fileExtension);
|
|
247
|
-
this.
|
|
243
|
+
const blobClient = this.storageClient.getContainerClient(this.containerName).getBlockBlobClient(filePath);
|
|
244
|
+
blobClient.download().then((downloadRes) => {
|
|
245
|
+
if (!downloadRes.readableStreamBody) {
|
|
246
|
+
throw new Error("Unable to parse the response data");
|
|
247
|
+
}
|
|
248
248
|
for (const [headerKey, headerValue] of Object.entries(
|
|
249
249
|
responseHeaders
|
|
250
250
|
)) {
|
|
251
251
|
res.setHeader(headerKey, headerValue);
|
|
252
252
|
}
|
|
253
|
-
|
|
253
|
+
downloadRes.readableStreamBody.pipe(res);
|
|
254
254
|
}).catch((e) => {
|
|
255
255
|
this.logger.warn(
|
|
256
256
|
`TechDocs Azure router failed to serve content from container ${this.containerName} at path ${filePath}: ${e.message}`
|
|
257
257
|
);
|
|
258
|
-
res.
|
|
258
|
+
if (!res.headersSent) {
|
|
259
|
+
res.status(404).send("File Not Found");
|
|
260
|
+
} else {
|
|
261
|
+
res.destroy();
|
|
262
|
+
}
|
|
259
263
|
});
|
|
260
264
|
};
|
|
261
265
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"azureBlobStorage.cjs.js","sources":["../../../src/stages/publish/azureBlobStorage.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 */\nimport { DefaultAzureCredential } from '@azure/identity';\nimport {\n BlobServiceClient,\n ContainerClient,\n StorageSharedKeyCredential,\n} from '@azure/storage-blob';\nimport { Entity, CompoundEntityRef } from '@backstage/catalog-model';\nimport { Config } from '@backstage/config';\nimport { assertError, ForwardedError } from '@backstage/errors';\nimport express from 'express';\nimport JSON5 from 'json5';\nimport limiterFactory from 'p-limit';\nimport { default as path, default as platformPath } from 'path';\nimport {\n bulkStorageOperation,\n getCloudPathForLocalPath,\n getFileTreeRecursively,\n getHeadersForFileExtension,\n lowerCaseEntityTriplet,\n getStaleFiles,\n lowerCaseEntityTripletInStoragePath,\n} from './helpers';\nimport {\n PublisherBase,\n PublishRequest,\n PublishResponse,\n ReadinessResponse,\n TechDocsMetadata,\n} from './types';\nimport { LoggerService } from '@backstage/backend-plugin-api';\n\n// The number of batches that may be ongoing at the same time.\nconst BATCH_CONCURRENCY = 3;\n\nexport class AzureBlobStoragePublish implements PublisherBase {\n private readonly storageClient: BlobServiceClient;\n private readonly containerName: string;\n private readonly legacyPathCasing: boolean;\n private readonly logger: LoggerService;\n\n constructor(options: {\n storageClient: BlobServiceClient;\n containerName: string;\n legacyPathCasing: boolean;\n logger: LoggerService;\n }) {\n this.storageClient = options.storageClient;\n this.containerName = options.containerName;\n this.legacyPathCasing = options.legacyPathCasing;\n this.logger = options.logger;\n }\n\n static fromConfig(config: Config, logger: LoggerService): PublisherBase {\n let storageClient: BlobServiceClient;\n let containerName = '';\n try {\n containerName = config.getString(\n 'techdocs.publisher.azureBlobStorage.containerName',\n );\n } catch (error) {\n throw new Error(\n \"Since techdocs.publisher.type is set to 'azureBlobStorage' in your app config, \" +\n 'techdocs.publisher.azureBlobStorage.containerName is required.',\n );\n }\n\n const legacyPathCasing =\n config.getOptionalBoolean(\n 'techdocs.legacyUseCaseSensitiveTripletPaths',\n ) || false;\n\n // Give more priority for connectionString, if configured, return the AzureBlobStoragePublish object here itself\n const connectionStringKey =\n 'techdocs.publisher.azureBlobStorage.connectionString';\n const connectionString = config.getOptionalString(connectionStringKey);\n\n if (connectionString) {\n logger.info(\n `Using '${connectionStringKey}' configuration to create storage client`,\n );\n storageClient = BlobServiceClient.fromConnectionString(connectionString);\n } else {\n let accountName = '';\n try {\n accountName = config.getString(\n 'techdocs.publisher.azureBlobStorage.credentials.accountName',\n );\n } catch (error) {\n throw new Error(\n \"Since techdocs.publisher.type is set to 'azureBlobStorage' in your app config, \" +\n 'techdocs.publisher.azureBlobStorage.credentials.accountName is required.',\n );\n }\n\n // Credentials is an optional config. If missing, default Azure Blob Storage environment variables will be used.\n // https://docs.microsoft.com/en-us/azure/storage/common/storage-auth-aad-app\n const accountKey = config.getOptionalString(\n 'techdocs.publisher.azureBlobStorage.credentials.accountKey',\n );\n\n let credential;\n if (accountKey) {\n credential = new StorageSharedKeyCredential(accountName, accountKey);\n } else {\n credential = new DefaultAzureCredential();\n }\n\n storageClient = new BlobServiceClient(\n `https://${accountName}.blob.core.windows.net`,\n credential,\n );\n }\n\n return new AzureBlobStoragePublish({\n storageClient: storageClient,\n containerName: containerName,\n legacyPathCasing: legacyPathCasing,\n logger: logger,\n });\n }\n\n async getReadiness(): Promise<ReadinessResponse> {\n try {\n const response = await this.storageClient\n .getContainerClient(this.containerName)\n .getProperties();\n\n if (response._response.status === 200) {\n return {\n isAvailable: true,\n };\n }\n\n if (response._response.status >= 400) {\n this.logger.error(\n `Failed to retrieve metadata from ${response._response.request.url} with status code ${response._response.status}.`,\n );\n }\n } catch (e) {\n assertError(e);\n this.logger.error(`from Azure Blob Storage client library: ${e.message}`);\n }\n\n this.logger.error(\n `Could not retrieve metadata about the Azure Blob Storage container ${this.containerName}. ` +\n 'Make sure that the Azure project and container exist and the access key is setup correctly ' +\n 'techdocs.publisher.azureBlobStorage.credentials defined in app config has correct permissions. ' +\n 'Refer to https://backstage.io/docs/features/techdocs/using-cloud-storage',\n );\n\n return { isAvailable: false };\n }\n\n /**\n * Upload all the files from the generated `directory` to the Azure Blob Storage container.\n * Directory structure used in the container is - entityNamespace/entityKind/entityName/index.html\n */\n async publish({\n entity,\n directory,\n }: PublishRequest): Promise<PublishResponse> {\n const objects: string[] = [];\n const useLegacyPathCasing = this.legacyPathCasing;\n\n // First, try to retrieve a list of all individual files currently existing\n const remoteFolder = getCloudPathForLocalPath(\n entity,\n undefined,\n useLegacyPathCasing,\n );\n let existingFiles: string[] = [];\n try {\n existingFiles = await this.getAllBlobsFromContainer({\n prefix: remoteFolder,\n maxPageSize: BATCH_CONCURRENCY,\n });\n } catch (e) {\n assertError(e);\n this.logger.error(\n `Unable to list files for Entity ${entity.metadata.name}: ${e.message}`,\n );\n }\n\n // Then, merge new files into the same folder\n let absoluteFilesToUpload;\n let container: ContainerClient;\n try {\n // Remove the absolute path prefix of the source directory\n // Path of all files to upload, relative to the root of the source directory\n // e.g. ['index.html', 'sub-page/index.html', 'assets/images/favicon.png']\n absoluteFilesToUpload = await getFileTreeRecursively(directory);\n\n container = this.storageClient.getContainerClient(this.containerName);\n const failedOperations: Error[] = [];\n await bulkStorageOperation(\n async absoluteFilePath => {\n const relativeFilePath = path.normalize(\n path.relative(directory, absoluteFilePath),\n );\n const remotePath = getCloudPathForLocalPath(\n entity,\n relativeFilePath,\n useLegacyPathCasing,\n );\n objects.push(remotePath);\n const response = await container\n .getBlockBlobClient(remotePath)\n .uploadFile(absoluteFilePath);\n\n if (response._response.status >= 400) {\n failedOperations.push(\n new Error(\n `Upload failed for ${absoluteFilePath} with status code ${response._response.status}`,\n ),\n );\n }\n\n return response;\n },\n absoluteFilesToUpload,\n { concurrencyLimit: BATCH_CONCURRENCY },\n );\n\n if (failedOperations.length > 0) {\n throw new Error(\n failedOperations\n .map(r => r.message)\n .filter(Boolean)\n .join(' '),\n );\n }\n\n this.logger.info(\n `Successfully uploaded all the generated files for Entity ${entity.metadata.name}. Total number of files: ${absoluteFilesToUpload.length}`,\n );\n } catch (e) {\n const errorMessage = `Unable to upload file(s) to Azure. ${e}`;\n this.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n\n // Last, try to remove the files that were *only* present previously\n try {\n const relativeFilesToUpload = absoluteFilesToUpload.map(\n absoluteFilePath =>\n getCloudPathForLocalPath(\n entity,\n path.relative(directory, absoluteFilePath),\n useLegacyPathCasing,\n ),\n );\n\n const staleFiles = getStaleFiles(relativeFilesToUpload, existingFiles);\n\n await bulkStorageOperation(\n async relativeFilePath => {\n return await container.deleteBlob(relativeFilePath);\n },\n staleFiles,\n { concurrencyLimit: BATCH_CONCURRENCY },\n );\n\n this.logger.info(\n `Successfully deleted stale files for Entity ${entity.metadata.name}. Total number of files: ${staleFiles.length}`,\n );\n } catch (error) {\n const errorMessage = `Unable to delete file(s) from Azure. ${error}`;\n this.logger.error(errorMessage);\n }\n\n return { objects };\n }\n\n private download(containerName: string, blobPath: string): Promise<Buffer> {\n return new Promise((resolve, reject) => {\n const fileStreamChunks: Array<any> = [];\n this.storageClient\n .getContainerClient(containerName)\n .getBlockBlobClient(blobPath)\n .download()\n .then(res => {\n const body = res.readableStreamBody;\n if (!body) {\n reject(new Error(`Unable to parse the response data`));\n return;\n }\n body\n .on('error', reject)\n .on('data', chunk => {\n fileStreamChunks.push(chunk);\n })\n .on('end', () => {\n resolve(Buffer.concat(fileStreamChunks));\n });\n })\n .catch(reject);\n });\n }\n\n async fetchTechDocsMetadata(\n entityName: CompoundEntityRef,\n ): Promise<TechDocsMetadata> {\n const entityTriplet = `${entityName.namespace}/${entityName.kind}/${entityName.name}`;\n const entityRootDir = this.legacyPathCasing\n ? entityTriplet\n : lowerCaseEntityTriplet(entityTriplet);\n\n try {\n const techdocsMetadataJson = await this.download(\n this.containerName,\n `${entityRootDir}/techdocs_metadata.json`,\n );\n if (!techdocsMetadataJson) {\n throw new Error(\n `Unable to parse the techdocs metadata file ${entityRootDir}/techdocs_metadata.json.`,\n );\n }\n const techdocsMetadata = JSON5.parse(\n techdocsMetadataJson.toString('utf-8'),\n );\n return techdocsMetadata;\n } catch (e) {\n throw new ForwardedError('TechDocs metadata fetch failed', e);\n }\n }\n\n /**\n * Express route middleware to serve static files on a route in techdocs-backend.\n */\n docsRouter(): express.Handler {\n return (req, res) => {\n // Decode and trim the leading forward slash\n const decodedUri = decodeURI(req.path.replace(/^\\//, ''));\n\n // filePath example - /default/Component/documented-component/index.html\n const filePath = this.legacyPathCasing\n ? decodedUri\n : lowerCaseEntityTripletInStoragePath(decodedUri);\n\n // Files with different extensions (CSS, HTML) need to be served with different headers\n const fileExtension = platformPath.extname(filePath);\n const responseHeaders = getHeadersForFileExtension(fileExtension);\n\n this.download(this.containerName, filePath)\n .then(fileContent => {\n // Inject response headers\n for (const [headerKey, headerValue] of Object.entries(\n responseHeaders,\n )) {\n res.setHeader(headerKey, headerValue);\n }\n res.send(fileContent);\n })\n .catch(e => {\n this.logger.warn(\n `TechDocs Azure router failed to serve content from container ${this.containerName} at path ${filePath}: ${e.message}`,\n );\n res.status(404).send('File Not Found');\n });\n };\n }\n\n /**\n * A helper function which checks if index.html of an Entity's docs site is available. This\n * can be used to verify if there are any pre-generated docs available to serve.\n */\n hasDocsBeenGenerated(entity: Entity): Promise<boolean> {\n const entityTriplet = `${entity.metadata.namespace}/${entity.kind}/${entity.metadata.name}`;\n const entityRootDir = this.legacyPathCasing\n ? entityTriplet\n : lowerCaseEntityTriplet(entityTriplet);\n\n return this.storageClient\n .getContainerClient(this.containerName)\n .getBlockBlobClient(`${entityRootDir}/index.html`)\n .exists();\n }\n\n protected async renameBlob(\n originalName: string,\n newName: string,\n removeOriginal = false,\n ): Promise<void> {\n const container = this.storageClient.getContainerClient(this.containerName);\n const blob = container.getBlobClient(newName);\n const { url } = container.getBlobClient(originalName);\n const response = await blob.beginCopyFromURL(url);\n await response.pollUntilDone();\n if (removeOriginal) {\n await container.deleteBlob(originalName);\n }\n }\n\n protected async renameBlobToLowerCase(\n originalPath: string,\n removeOriginal: boolean,\n ) {\n let newPath;\n try {\n newPath = lowerCaseEntityTripletInStoragePath(originalPath);\n } catch (e) {\n assertError(e);\n this.logger.warn(e.message);\n return;\n }\n\n if (originalPath === newPath) return;\n try {\n this.logger.debug(`Migrating ${originalPath}`);\n await this.renameBlob(originalPath, newPath, removeOriginal);\n } catch (e) {\n assertError(e);\n this.logger.warn(`Unable to migrate ${originalPath}: ${e.message}`);\n }\n }\n\n async migrateDocsCase({\n removeOriginal = false,\n concurrency = 25,\n }): Promise<void> {\n const promises = [];\n const limiter = limiterFactory(concurrency);\n const container = this.storageClient.getContainerClient(this.containerName);\n\n for await (const blob of container.listBlobsFlat()) {\n promises.push(\n limiter(\n this.renameBlobToLowerCase.bind(this),\n blob.name,\n removeOriginal,\n ),\n );\n }\n\n await Promise.all(promises);\n }\n\n protected async getAllBlobsFromContainer({\n prefix,\n maxPageSize,\n }: {\n prefix: string;\n maxPageSize: number;\n }): Promise<string[]> {\n const blobs: string[] = [];\n const container = this.storageClient.getContainerClient(this.containerName);\n\n let iterator = container.listBlobsFlat({ prefix }).byPage({ maxPageSize });\n let response = (await iterator.next()).value;\n\n do {\n for (const blob of response?.segment?.blobItems ?? []) {\n blobs.push(blob.name);\n }\n iterator = container\n .listBlobsFlat({ prefix })\n .byPage({ continuationToken: response.continuationToken, maxPageSize });\n response = (await iterator.next()).value;\n } while (response && response.continuationToken);\n\n return blobs;\n }\n}\n"],"names":["BlobServiceClient","StorageSharedKeyCredential","DefaultAzureCredential","assertError","getCloudPathForLocalPath","getFileTreeRecursively","bulkStorageOperation","path","getStaleFiles","lowerCaseEntityTriplet","JSON5","ForwardedError","lowerCaseEntityTripletInStoragePath","platformPath","getHeadersForFileExtension","limiterFactory"],"mappings":";;;;;;;;;;;;;;;;AA+CA,MAAM,iBAAoB,GAAA,CAAA;AAEnB,MAAM,uBAAiD,CAAA;AAAA,EAC3C,aAAA;AAAA,EACA,aAAA;AAAA,EACA,gBAAA;AAAA,EACA,MAAA;AAAA,EAEjB,YAAY,OAKT,EAAA;AACD,IAAA,IAAA,CAAK,gBAAgB,OAAQ,CAAA,aAAA;AAC7B,IAAA,IAAA,CAAK,gBAAgB,OAAQ,CAAA,aAAA;AAC7B,IAAA,IAAA,CAAK,mBAAmB,OAAQ,CAAA,gBAAA;AAChC,IAAA,IAAA,CAAK,SAAS,OAAQ,CAAA,MAAA;AAAA;AACxB,EAEA,OAAO,UAAW,CAAA,MAAA,EAAgB,MAAsC,EAAA;AACtE,IAAI,IAAA,aAAA;AACJ,IAAA,IAAI,aAAgB,GAAA,EAAA;AACpB,IAAI,IAAA;AACF,MAAA,aAAA,GAAgB,MAAO,CAAA,SAAA;AAAA,QACrB;AAAA,OACF;AAAA,aACO,KAAO,EAAA;AACd,MAAA,MAAM,IAAI,KAAA;AAAA,QACR;AAAA,OAEF;AAAA;AAGF,IAAA,MAAM,mBACJ,MAAO,CAAA,kBAAA;AAAA,MACL;AAAA,KACG,IAAA,KAAA;AAGP,IAAA,MAAM,mBACJ,GAAA,sDAAA;AACF,IAAM,MAAA,gBAAA,GAAmB,MAAO,CAAA,iBAAA,CAAkB,mBAAmB,CAAA;AAErE,IAAA,IAAI,gBAAkB,EAAA;AACpB,MAAO,MAAA,CAAA,IAAA;AAAA,QACL,UAAU,mBAAmB,CAAA,wCAAA;AAAA,OAC/B;AACA,MAAgB,aAAA,GAAAA,6BAAA,CAAkB,qBAAqB,gBAAgB,CAAA;AAAA,KAClE,MAAA;AACL,MAAA,IAAI,WAAc,GAAA,EAAA;AAClB,MAAI,IAAA;AACF,QAAA,WAAA,GAAc,MAAO,CAAA,SAAA;AAAA,UACnB;AAAA,SACF;AAAA,eACO,KAAO,EAAA;AACd,QAAA,MAAM,IAAI,KAAA;AAAA,UACR;AAAA,SAEF;AAAA;AAKF,MAAA,MAAM,aAAa,MAAO,CAAA,iBAAA;AAAA,QACxB;AAAA,OACF;AAEA,MAAI,IAAA,UAAA;AACJ,MAAA,IAAI,UAAY,EAAA;AACd,QAAa,UAAA,GAAA,IAAIC,sCAA2B,CAAA,WAAA,EAAa,UAAU,CAAA;AAAA,OAC9D,MAAA;AACL,QAAA,UAAA,GAAa,IAAIC,+BAAuB,EAAA;AAAA;AAG1C,MAAA,aAAA,GAAgB,IAAIF,6BAAA;AAAA,QAClB,WAAW,WAAW,CAAA,sBAAA,CAAA;AAAA,QACtB;AAAA,OACF;AAAA;AAGF,IAAA,OAAO,IAAI,uBAAwB,CAAA;AAAA,MACjC,aAAA;AAAA,MACA,aAAA;AAAA,MACA,gBAAA;AAAA,MACA;AAAA,KACD,CAAA;AAAA;AACH,EAEA,MAAM,YAA2C,GAAA;AAC/C,IAAI,IAAA;AACF,MAAM,MAAA,QAAA,GAAW,MAAM,IAAK,CAAA,aAAA,CACzB,mBAAmB,IAAK,CAAA,aAAa,EACrC,aAAc,EAAA;AAEjB,MAAI,IAAA,QAAA,CAAS,SAAU,CAAA,MAAA,KAAW,GAAK,EAAA;AACrC,QAAO,OAAA;AAAA,UACL,WAAa,EAAA;AAAA,SACf;AAAA;AAGF,MAAI,IAAA,QAAA,CAAS,SAAU,CAAA,MAAA,IAAU,GAAK,EAAA;AACpC,QAAA,IAAA,CAAK,MAAO,CAAA,KAAA;AAAA,UACV,CAAA,iCAAA,EAAoC,SAAS,SAAU,CAAA,OAAA,CAAQ,GAAG,CAAqB,kBAAA,EAAA,QAAA,CAAS,UAAU,MAAM,CAAA,CAAA;AAAA,SAClH;AAAA;AACF,aACO,CAAG,EAAA;AACV,MAAAG,kBAAA,CAAY,CAAC,CAAA;AACb,MAAA,IAAA,CAAK,MAAO,CAAA,KAAA,CAAM,CAA2C,wCAAA,EAAA,CAAA,CAAE,OAAO,CAAE,CAAA,CAAA;AAAA;AAG1E,IAAA,IAAA,CAAK,MAAO,CAAA,KAAA;AAAA,MACV,CAAA,mEAAA,EAAsE,KAAK,aAAa,CAAA,oQAAA;AAAA,KAI1F;AAEA,IAAO,OAAA,EAAE,aAAa,KAAM,EAAA;AAAA;AAC9B;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,OAAQ,CAAA;AAAA,IACZ,MAAA;AAAA,IACA;AAAA,GAC2C,EAAA;AAC3C,IAAA,MAAM,UAAoB,EAAC;AAC3B,IAAA,MAAM,sBAAsB,IAAK,CAAA,gBAAA;AAGjC,IAAA,MAAM,YAAe,GAAAC,gCAAA;AAAA,MACnB,MAAA;AAAA,MACA,KAAA,CAAA;AAAA,MACA;AAAA,KACF;AACA,IAAA,IAAI,gBAA0B,EAAC;AAC/B,IAAI,IAAA;AACF,MAAgB,aAAA,GAAA,MAAM,KAAK,wBAAyB,CAAA;AAAA,QAClD,MAAQ,EAAA,YAAA;AAAA,QACR,WAAa,EAAA;AAAA,OACd,CAAA;AAAA,aACM,CAAG,EAAA;AACV,MAAAD,kBAAA,CAAY,CAAC,CAAA;AACb,MAAA,IAAA,CAAK,MAAO,CAAA,KAAA;AAAA,QACV,mCAAmC,MAAO,CAAA,QAAA,CAAS,IAAI,CAAA,EAAA,EAAK,EAAE,OAAO,CAAA;AAAA,OACvE;AAAA;AAIF,IAAI,IAAA,qBAAA;AACJ,IAAI,IAAA,SAAA;AACJ,IAAI,IAAA;AAIF,MAAwB,qBAAA,GAAA,MAAME,+BAAuB,SAAS,CAAA;AAE9D,MAAA,SAAA,GAAY,IAAK,CAAA,aAAA,CAAc,kBAAmB,CAAA,IAAA,CAAK,aAAa,CAAA;AACpE,MAAA,MAAM,mBAA4B,EAAC;AACnC,MAAM,MAAAC,4BAAA;AAAA,QACJ,OAAM,gBAAoB,KAAA;AACxB,UAAA,MAAM,mBAAmBC,qBAAK,CAAA,SAAA;AAAA,YAC5BA,qBAAA,CAAK,QAAS,CAAA,SAAA,EAAW,gBAAgB;AAAA,WAC3C;AACA,UAAA,MAAM,UAAa,GAAAH,gCAAA;AAAA,YACjB,MAAA;AAAA,YACA,gBAAA;AAAA,YACA;AAAA,WACF;AACA,UAAA,OAAA,CAAQ,KAAK,UAAU,CAAA;AACvB,UAAA,MAAM,WAAW,MAAM,SAAA,CACpB,mBAAmB,UAAU,CAAA,CAC7B,WAAW,gBAAgB,CAAA;AAE9B,UAAI,IAAA,QAAA,CAAS,SAAU,CAAA,MAAA,IAAU,GAAK,EAAA;AACpC,YAAiB,gBAAA,CAAA,IAAA;AAAA,cACf,IAAI,KAAA;AAAA,gBACF,CAAqB,kBAAA,EAAA,gBAAgB,CAAqB,kBAAA,EAAA,QAAA,CAAS,UAAU,MAAM,CAAA;AAAA;AACrF,aACF;AAAA;AAGF,UAAO,OAAA,QAAA;AAAA,SACT;AAAA,QACA,qBAAA;AAAA,QACA,EAAE,kBAAkB,iBAAkB;AAAA,OACxC;AAEA,MAAI,IAAA,gBAAA,CAAiB,SAAS,CAAG,EAAA;AAC/B,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,gBAAA,CACG,GAAI,CAAA,CAAA,CAAA,KAAK,CAAE,CAAA,OAAO,EAClB,MAAO,CAAA,OAAO,CACd,CAAA,IAAA,CAAK,GAAG;AAAA,SACb;AAAA;AAGF,MAAA,IAAA,CAAK,MAAO,CAAA,IAAA;AAAA,QACV,4DAA4D,MAAO,CAAA,QAAA,CAAS,IAAI,CAAA,yBAAA,EAA4B,sBAAsB,MAAM,CAAA;AAAA,OAC1I;AAAA,aACO,CAAG,EAAA;AACV,MAAM,MAAA,YAAA,GAAe,sCAAsC,CAAC,CAAA,CAAA;AAC5D,MAAK,IAAA,CAAA,MAAA,CAAO,MAAM,YAAY,CAAA;AAC9B,MAAM,MAAA,IAAI,MAAM,YAAY,CAAA;AAAA;AAI9B,IAAI,IAAA;AACF,MAAA,MAAM,wBAAwB,qBAAsB,CAAA,GAAA;AAAA,QAClD,CACE,gBAAA,KAAAA,gCAAA;AAAA,UACE,MAAA;AAAA,UACAG,qBAAA,CAAK,QAAS,CAAA,SAAA,EAAW,gBAAgB,CAAA;AAAA,UACzC;AAAA;AACF,OACJ;AAEA,MAAM,MAAA,UAAA,GAAaC,qBAAc,CAAA,qBAAA,EAAuB,aAAa,CAAA;AAErE,MAAM,MAAAF,4BAAA;AAAA,QACJ,OAAM,gBAAoB,KAAA;AACxB,UAAO,OAAA,MAAM,SAAU,CAAA,UAAA,CAAW,gBAAgB,CAAA;AAAA,SACpD;AAAA,QACA,UAAA;AAAA,QACA,EAAE,kBAAkB,iBAAkB;AAAA,OACxC;AAEA,MAAA,IAAA,CAAK,MAAO,CAAA,IAAA;AAAA,QACV,+CAA+C,MAAO,CAAA,QAAA,CAAS,IAAI,CAAA,yBAAA,EAA4B,WAAW,MAAM,CAAA;AAAA,OAClH;AAAA,aACO,KAAO,EAAA;AACd,MAAM,MAAA,YAAA,GAAe,wCAAwC,KAAK,CAAA,CAAA;AAClE,MAAK,IAAA,CAAA,MAAA,CAAO,MAAM,YAAY,CAAA;AAAA;AAGhC,IAAA,OAAO,EAAE,OAAQ,EAAA;AAAA;AACnB,EAEQ,QAAA,CAAS,eAAuB,QAAmC,EAAA;AACzE,IAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAW,KAAA;AACtC,MAAA,MAAM,mBAA+B,EAAC;AACtC,MAAK,IAAA,CAAA,aAAA,CACF,kBAAmB,CAAA,aAAa,CAChC,CAAA,kBAAA,CAAmB,QAAQ,CAC3B,CAAA,QAAA,EACA,CAAA,IAAA,CAAK,CAAO,GAAA,KAAA;AACX,QAAA,MAAM,OAAO,GAAI,CAAA,kBAAA;AACjB,QAAA,IAAI,CAAC,IAAM,EAAA;AACT,UAAO,MAAA,CAAA,IAAI,KAAM,CAAA,CAAA,iCAAA,CAAmC,CAAC,CAAA;AACrD,UAAA;AAAA;AAEF,QAAA,IAAA,CACG,GAAG,OAAS,EAAA,MAAM,CAClB,CAAA,EAAA,CAAG,QAAQ,CAAS,KAAA,KAAA;AACnB,UAAA,gBAAA,CAAiB,KAAK,KAAK,CAAA;AAAA,SAC5B,CAAA,CACA,EAAG,CAAA,KAAA,EAAO,MAAM;AACf,UAAQ,OAAA,CAAA,MAAA,CAAO,MAAO,CAAA,gBAAgB,CAAC,CAAA;AAAA,SACxC,CAAA;AAAA,OACJ,CACA,CAAA,KAAA,CAAM,MAAM,CAAA;AAAA,KAChB,CAAA;AAAA;AACH,EAEA,MAAM,sBACJ,UAC2B,EAAA;AAC3B,IAAM,MAAA,aAAA,GAAgB,GAAG,UAAW,CAAA,SAAS,IAAI,UAAW,CAAA,IAAI,CAAI,CAAA,EAAA,UAAA,CAAW,IAAI,CAAA,CAAA;AACnF,IAAA,MAAM,aAAgB,GAAA,IAAA,CAAK,gBACvB,GAAA,aAAA,GACAG,+BAAuB,aAAa,CAAA;AAExC,IAAI,IAAA;AACF,MAAM,MAAA,oBAAA,GAAuB,MAAM,IAAK,CAAA,QAAA;AAAA,QACtC,IAAK,CAAA,aAAA;AAAA,QACL,GAAG,aAAa,CAAA,uBAAA;AAAA,OAClB;AACA,MAAA,IAAI,CAAC,oBAAsB,EAAA;AACzB,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,8CAA8C,aAAa,CAAA,wBAAA;AAAA,SAC7D;AAAA;AAEF,MAAA,MAAM,mBAAmBC,sBAAM,CAAA,KAAA;AAAA,QAC7B,oBAAA,CAAqB,SAAS,OAAO;AAAA,OACvC;AACA,MAAO,OAAA,gBAAA;AAAA,aACA,CAAG,EAAA;AACV,MAAM,MAAA,IAAIC,qBAAe,CAAA,gCAAA,EAAkC,CAAC,CAAA;AAAA;AAC9D;AACF;AAAA;AAAA;AAAA,EAKA,UAA8B,GAAA;AAC5B,IAAO,OAAA,CAAC,KAAK,GAAQ,KAAA;AAEnB,MAAA,MAAM,aAAa,SAAU,CAAA,GAAA,CAAI,KAAK,OAAQ,CAAA,KAAA,EAAO,EAAE,CAAC,CAAA;AAGxD,MAAA,MAAM,QAAW,GAAA,IAAA,CAAK,gBAClB,GAAA,UAAA,GACAC,4CAAoC,UAAU,CAAA;AAGlD,MAAM,MAAA,aAAA,GAAgBC,qBAAa,CAAA,OAAA,CAAQ,QAAQ,CAAA;AACnD,MAAM,MAAA,eAAA,GAAkBC,mCAA2B,aAAa,CAAA;AAEhE,MAAA,IAAA,CAAK,SAAS,IAAK,CAAA,aAAA,EAAe,QAAQ,CAAA,CACvC,KAAK,CAAe,WAAA,KAAA;AAEnB,QAAA,KAAA,MAAW,CAAC,SAAA,EAAW,WAAW,CAAA,IAAK,MAAO,CAAA,OAAA;AAAA,UAC5C;AAAA,SACC,EAAA;AACD,UAAI,GAAA,CAAA,SAAA,CAAU,WAAW,WAAW,CAAA;AAAA;AAEtC,QAAA,GAAA,CAAI,KAAK,WAAW,CAAA;AAAA,OACrB,CACA,CAAA,KAAA,CAAM,CAAK,CAAA,KAAA;AACV,QAAA,IAAA,CAAK,MAAO,CAAA,IAAA;AAAA,UACV,gEAAgE,IAAK,CAAA,aAAa,YAAY,QAAQ,CAAA,EAAA,EAAK,EAAE,OAAO,CAAA;AAAA,SACtH;AACA,QAAA,GAAA,CAAI,MAAO,CAAA,GAAG,CAAE,CAAA,IAAA,CAAK,gBAAgB,CAAA;AAAA,OACtC,CAAA;AAAA,KACL;AAAA;AACF;AAAA;AAAA;AAAA;AAAA,EAMA,qBAAqB,MAAkC,EAAA;AACrD,IAAM,MAAA,aAAA,GAAgB,CAAG,EAAA,MAAA,CAAO,QAAS,CAAA,SAAS,CAAI,CAAA,EAAA,MAAA,CAAO,IAAI,CAAA,CAAA,EAAI,MAAO,CAAA,QAAA,CAAS,IAAI,CAAA,CAAA;AACzF,IAAA,MAAM,aAAgB,GAAA,IAAA,CAAK,gBACvB,GAAA,aAAA,GACAL,+BAAuB,aAAa,CAAA;AAExC,IAAO,OAAA,IAAA,CAAK,aACT,CAAA,kBAAA,CAAmB,IAAK,CAAA,aAAa,CACrC,CAAA,kBAAA,CAAmB,CAAG,EAAA,aAAa,CAAa,WAAA,CAAA,CAAA,CAChD,MAAO,EAAA;AAAA;AACZ,EAEA,MAAgB,UAAA,CACd,YACA,EAAA,OAAA,EACA,iBAAiB,KACF,EAAA;AACf,IAAA,MAAM,SAAY,GAAA,IAAA,CAAK,aAAc,CAAA,kBAAA,CAAmB,KAAK,aAAa,CAAA;AAC1E,IAAM,MAAA,IAAA,GAAO,SAAU,CAAA,aAAA,CAAc,OAAO,CAAA;AAC5C,IAAA,MAAM,EAAE,GAAA,EAAQ,GAAA,SAAA,CAAU,cAAc,YAAY,CAAA;AACpD,IAAA,MAAM,QAAW,GAAA,MAAM,IAAK,CAAA,gBAAA,CAAiB,GAAG,CAAA;AAChD,IAAA,MAAM,SAAS,aAAc,EAAA;AAC7B,IAAA,IAAI,cAAgB,EAAA;AAClB,MAAM,MAAA,SAAA,CAAU,WAAW,YAAY,CAAA;AAAA;AACzC;AACF,EAEA,MAAgB,qBACd,CAAA,YAAA,EACA,cACA,EAAA;AACA,IAAI,IAAA,OAAA;AACJ,IAAI,IAAA;AACF,MAAA,OAAA,GAAUG,4CAAoC,YAAY,CAAA;AAAA,aACnD,CAAG,EAAA;AACV,MAAAT,kBAAA,CAAY,CAAC,CAAA;AACb,MAAK,IAAA,CAAA,MAAA,CAAO,IAAK,CAAA,CAAA,CAAE,OAAO,CAAA;AAC1B,MAAA;AAAA;AAGF,IAAA,IAAI,iBAAiB,OAAS,EAAA;AAC9B,IAAI,IAAA;AACF,MAAA,IAAA,CAAK,MAAO,CAAA,KAAA,CAAM,CAAa,UAAA,EAAA,YAAY,CAAE,CAAA,CAAA;AAC7C,MAAA,MAAM,IAAK,CAAA,UAAA,CAAW,YAAc,EAAA,OAAA,EAAS,cAAc,CAAA;AAAA,aACpD,CAAG,EAAA;AACV,MAAAA,kBAAA,CAAY,CAAC,CAAA;AACb,MAAA,IAAA,CAAK,OAAO,IAAK,CAAA,CAAA,kBAAA,EAAqB,YAAY,CAAK,EAAA,EAAA,CAAA,CAAE,OAAO,CAAE,CAAA,CAAA;AAAA;AACpE;AACF,EAEA,MAAM,eAAgB,CAAA;AAAA,IACpB,cAAiB,GAAA,KAAA;AAAA,IACjB,WAAc,GAAA;AAAA,GACE,EAAA;AAChB,IAAA,MAAM,WAAW,EAAC;AAClB,IAAM,MAAA,OAAA,GAAUY,+BAAe,WAAW,CAAA;AAC1C,IAAA,MAAM,SAAY,GAAA,IAAA,CAAK,aAAc,CAAA,kBAAA,CAAmB,KAAK,aAAa,CAAA;AAE1E,IAAiB,WAAA,MAAA,IAAA,IAAQ,SAAU,CAAA,aAAA,EAAiB,EAAA;AAClD,MAAS,QAAA,CAAA,IAAA;AAAA,QACP,OAAA;AAAA,UACE,IAAA,CAAK,qBAAsB,CAAA,IAAA,CAAK,IAAI,CAAA;AAAA,UACpC,IAAK,CAAA,IAAA;AAAA,UACL;AAAA;AACF,OACF;AAAA;AAGF,IAAM,MAAA,OAAA,CAAQ,IAAI,QAAQ,CAAA;AAAA;AAC5B,EAEA,MAAgB,wBAAyB,CAAA;AAAA,IACvC,MAAA;AAAA,IACA;AAAA,GAIoB,EAAA;AACpB,IAAA,MAAM,QAAkB,EAAC;AACzB,IAAA,MAAM,SAAY,GAAA,IAAA,CAAK,aAAc,CAAA,kBAAA,CAAmB,KAAK,aAAa,CAAA;AAE1E,IAAI,IAAA,QAAA,GAAW,SAAU,CAAA,aAAA,CAAc,EAAE,MAAA,EAAQ,CAAE,CAAA,MAAA,CAAO,EAAE,WAAA,EAAa,CAAA;AACzE,IAAA,IAAI,QAAY,GAAA,CAAA,MAAM,QAAS,CAAA,IAAA,EAAQ,EAAA,KAAA;AAEvC,IAAG,GAAA;AACD,MAAA,KAAA,MAAW,IAAQ,IAAA,QAAA,EAAU,OAAS,EAAA,SAAA,IAAa,EAAI,EAAA;AACrD,QAAM,KAAA,CAAA,IAAA,CAAK,KAAK,IAAI,CAAA;AAAA;AAEtB,MAAA,QAAA,GAAW,SACR,CAAA,aAAA,CAAc,EAAE,MAAA,EAAQ,CAAA,CACxB,MAAO,CAAA,EAAE,iBAAmB,EAAA,QAAA,CAAS,iBAAmB,EAAA,WAAA,EAAa,CAAA;AACxE,MAAY,QAAA,GAAA,CAAA,MAAM,QAAS,CAAA,IAAA,EAAQ,EAAA,KAAA;AAAA,KACrC,QAAS,YAAY,QAAS,CAAA,iBAAA;AAE9B,IAAO,OAAA,KAAA;AAAA;AAEX;;;;"}
|
|
1
|
+
{"version":3,"file":"azureBlobStorage.cjs.js","sources":["../../../src/stages/publish/azureBlobStorage.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 */\nimport { DefaultAzureCredential } from '@azure/identity';\nimport {\n BlobServiceClient,\n ContainerClient,\n StorageSharedKeyCredential,\n} from '@azure/storage-blob';\nimport { Entity, CompoundEntityRef } from '@backstage/catalog-model';\nimport { Config } from '@backstage/config';\nimport { assertError, ForwardedError } from '@backstage/errors';\nimport express from 'express';\nimport JSON5 from 'json5';\nimport limiterFactory from 'p-limit';\nimport { default as path, default as platformPath } from 'path';\nimport {\n bulkStorageOperation,\n getCloudPathForLocalPath,\n getFileTreeRecursively,\n getHeadersForFileExtension,\n lowerCaseEntityTriplet,\n getStaleFiles,\n lowerCaseEntityTripletInStoragePath,\n} from './helpers';\nimport {\n PublisherBase,\n PublishRequest,\n PublishResponse,\n ReadinessResponse,\n TechDocsMetadata,\n} from './types';\nimport { LoggerService } from '@backstage/backend-plugin-api';\n\n// The number of batches that may be ongoing at the same time.\nconst BATCH_CONCURRENCY = 3;\n\nexport class AzureBlobStoragePublish implements PublisherBase {\n private readonly storageClient: BlobServiceClient;\n private readonly containerName: string;\n private readonly legacyPathCasing: boolean;\n private readonly logger: LoggerService;\n\n constructor(options: {\n storageClient: BlobServiceClient;\n containerName: string;\n legacyPathCasing: boolean;\n logger: LoggerService;\n }) {\n this.storageClient = options.storageClient;\n this.containerName = options.containerName;\n this.legacyPathCasing = options.legacyPathCasing;\n this.logger = options.logger;\n }\n\n static fromConfig(config: Config, logger: LoggerService): PublisherBase {\n let storageClient: BlobServiceClient;\n let containerName = '';\n try {\n containerName = config.getString(\n 'techdocs.publisher.azureBlobStorage.containerName',\n );\n } catch (error) {\n throw new Error(\n \"Since techdocs.publisher.type is set to 'azureBlobStorage' in your app config, \" +\n 'techdocs.publisher.azureBlobStorage.containerName is required.',\n );\n }\n\n const legacyPathCasing =\n config.getOptionalBoolean(\n 'techdocs.legacyUseCaseSensitiveTripletPaths',\n ) || false;\n\n // Give more priority for connectionString, if configured, return the AzureBlobStoragePublish object here itself\n const connectionStringKey =\n 'techdocs.publisher.azureBlobStorage.connectionString';\n const connectionString = config.getOptionalString(connectionStringKey);\n\n if (connectionString) {\n logger.info(\n `Using '${connectionStringKey}' configuration to create storage client`,\n );\n storageClient = BlobServiceClient.fromConnectionString(connectionString);\n } else {\n let accountName = '';\n try {\n accountName = config.getString(\n 'techdocs.publisher.azureBlobStorage.credentials.accountName',\n );\n } catch (error) {\n throw new Error(\n \"Since techdocs.publisher.type is set to 'azureBlobStorage' in your app config, \" +\n 'techdocs.publisher.azureBlobStorage.credentials.accountName is required.',\n );\n }\n\n // Credentials is an optional config. If missing, default Azure Blob Storage environment variables will be used.\n // https://docs.microsoft.com/en-us/azure/storage/common/storage-auth-aad-app\n const accountKey = config.getOptionalString(\n 'techdocs.publisher.azureBlobStorage.credentials.accountKey',\n );\n\n let credential;\n if (accountKey) {\n credential = new StorageSharedKeyCredential(accountName, accountKey);\n } else {\n credential = new DefaultAzureCredential();\n }\n\n storageClient = new BlobServiceClient(\n `https://${accountName}.blob.core.windows.net`,\n credential,\n );\n }\n\n return new AzureBlobStoragePublish({\n storageClient: storageClient,\n containerName: containerName,\n legacyPathCasing: legacyPathCasing,\n logger: logger,\n });\n }\n\n async getReadiness(): Promise<ReadinessResponse> {\n try {\n const response = await this.storageClient\n .getContainerClient(this.containerName)\n .getProperties();\n\n if (response._response.status === 200) {\n return {\n isAvailable: true,\n };\n }\n\n if (response._response.status >= 400) {\n this.logger.error(\n `Failed to retrieve metadata from ${response._response.request.url} with status code ${response._response.status}.`,\n );\n }\n } catch (e) {\n assertError(e);\n this.logger.error(`from Azure Blob Storage client library: ${e.message}`);\n }\n\n this.logger.error(\n `Could not retrieve metadata about the Azure Blob Storage container ${this.containerName}. ` +\n 'Make sure that the Azure project and container exist and the access key is setup correctly ' +\n 'techdocs.publisher.azureBlobStorage.credentials defined in app config has correct permissions. ' +\n 'Refer to https://backstage.io/docs/features/techdocs/using-cloud-storage',\n );\n\n return { isAvailable: false };\n }\n\n /**\n * Upload all the files from the generated `directory` to the Azure Blob Storage container.\n * Directory structure used in the container is - entityNamespace/entityKind/entityName/index.html\n */\n async publish({\n entity,\n directory,\n }: PublishRequest): Promise<PublishResponse> {\n const objects: string[] = [];\n const useLegacyPathCasing = this.legacyPathCasing;\n\n // First, try to retrieve a list of all individual files currently existing\n const remoteFolder = getCloudPathForLocalPath(\n entity,\n undefined,\n useLegacyPathCasing,\n );\n let existingFiles: string[] = [];\n try {\n existingFiles = await this.getAllBlobsFromContainer({\n prefix: remoteFolder,\n maxPageSize: BATCH_CONCURRENCY,\n });\n } catch (e) {\n assertError(e);\n this.logger.error(\n `Unable to list files for Entity ${entity.metadata.name}: ${e.message}`,\n );\n }\n\n // Then, merge new files into the same folder\n let absoluteFilesToUpload;\n let container: ContainerClient;\n try {\n // Remove the absolute path prefix of the source directory\n // Path of all files to upload, relative to the root of the source directory\n // e.g. ['index.html', 'sub-page/index.html', 'assets/images/favicon.png']\n absoluteFilesToUpload = await getFileTreeRecursively(directory);\n\n container = this.storageClient.getContainerClient(this.containerName);\n const failedOperations: Error[] = [];\n await bulkStorageOperation(\n async absoluteFilePath => {\n const relativeFilePath = path.normalize(\n path.relative(directory, absoluteFilePath),\n );\n const remotePath = getCloudPathForLocalPath(\n entity,\n relativeFilePath,\n useLegacyPathCasing,\n );\n objects.push(remotePath);\n const response = await container\n .getBlockBlobClient(remotePath)\n .uploadFile(absoluteFilePath);\n\n if (response._response.status >= 400) {\n failedOperations.push(\n new Error(\n `Upload failed for ${absoluteFilePath} with status code ${response._response.status}`,\n ),\n );\n }\n\n return response;\n },\n absoluteFilesToUpload,\n { concurrencyLimit: BATCH_CONCURRENCY },\n );\n\n if (failedOperations.length > 0) {\n throw new Error(\n failedOperations\n .map(r => r.message)\n .filter(Boolean)\n .join(' '),\n );\n }\n\n this.logger.info(\n `Successfully uploaded all the generated files for Entity ${entity.metadata.name}. Total number of files: ${absoluteFilesToUpload.length}`,\n );\n } catch (e) {\n const errorMessage = `Unable to upload file(s) to Azure. ${e}`;\n this.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n\n // Last, try to remove the files that were *only* present previously\n try {\n const relativeFilesToUpload = absoluteFilesToUpload.map(\n absoluteFilePath =>\n getCloudPathForLocalPath(\n entity,\n path.relative(directory, absoluteFilePath),\n useLegacyPathCasing,\n ),\n );\n\n const staleFiles = getStaleFiles(relativeFilesToUpload, existingFiles);\n\n await bulkStorageOperation(\n async relativeFilePath => {\n return await container.deleteBlob(relativeFilePath);\n },\n staleFiles,\n { concurrencyLimit: BATCH_CONCURRENCY },\n );\n\n this.logger.info(\n `Successfully deleted stale files for Entity ${entity.metadata.name}. Total number of files: ${staleFiles.length}`,\n );\n } catch (error) {\n const errorMessage = `Unable to delete file(s) from Azure. ${error}`;\n this.logger.error(errorMessage);\n }\n\n return { objects };\n }\n\n async fetchTechDocsMetadata(\n entityName: CompoundEntityRef,\n ): Promise<TechDocsMetadata> {\n const entityTriplet = `${entityName.namespace}/${entityName.kind}/${entityName.name}`;\n const entityRootDir = this.legacyPathCasing\n ? entityTriplet\n : lowerCaseEntityTriplet(entityTriplet);\n\n try {\n const techdocsMetadataJson = await new Promise<Buffer>(\n (resolve, reject) => {\n const fileStreamChunks: Array<any> = [];\n this.storageClient\n .getContainerClient(this.containerName)\n .getBlockBlobClient(`${entityRootDir}/techdocs_metadata.json`)\n .download()\n .then(res => {\n const body = res.readableStreamBody;\n if (!body) {\n reject(new Error(`Unable to parse the response data`));\n return;\n }\n body\n .on('error', reject)\n .on('data', chunk => {\n fileStreamChunks.push(chunk);\n })\n .on('end', () => {\n resolve(Buffer.concat(fileStreamChunks));\n });\n })\n .catch(reject);\n },\n );\n\n if (!techdocsMetadataJson) {\n throw new Error(\n `Unable to parse the techdocs metadata file ${entityRootDir}/techdocs_metadata.json.`,\n );\n }\n const techdocsMetadata = JSON5.parse(\n techdocsMetadataJson.toString('utf-8'),\n );\n return techdocsMetadata;\n } catch (e) {\n throw new ForwardedError('TechDocs metadata fetch failed', e);\n }\n }\n\n /**\n * Express route middleware to serve static files on a route in techdocs-backend.\n */\n docsRouter(): express.Handler {\n return (req, res) => {\n // Decode and trim the leading forward slash\n const decodedUri = decodeURI(req.path.replace(/^\\//, ''));\n\n // filePath example - /default/Component/documented-component/index.html\n const filePath = this.legacyPathCasing\n ? decodedUri\n : lowerCaseEntityTripletInStoragePath(decodedUri);\n\n // Files with different extensions (CSS, HTML) need to be served with different headers\n const fileExtension = platformPath.extname(filePath);\n const responseHeaders = getHeadersForFileExtension(fileExtension);\n\n const blobClient = this.storageClient\n .getContainerClient(this.containerName)\n .getBlockBlobClient(filePath);\n\n blobClient\n .download()\n .then(downloadRes => {\n if (!downloadRes.readableStreamBody) {\n throw new Error('Unable to parse the response data');\n }\n for (const [headerKey, headerValue] of Object.entries(\n responseHeaders,\n )) {\n res.setHeader(headerKey, headerValue);\n }\n downloadRes.readableStreamBody.pipe(res);\n })\n .catch(e => {\n this.logger.warn(\n `TechDocs Azure router failed to serve content from container ${this.containerName} at path ${filePath}: ${e.message}`,\n );\n if (!res.headersSent) {\n res.status(404).send('File Not Found');\n } else {\n res.destroy();\n }\n });\n };\n }\n\n /**\n * A helper function which checks if index.html of an Entity's docs site is available. This\n * can be used to verify if there are any pre-generated docs available to serve.\n */\n hasDocsBeenGenerated(entity: Entity): Promise<boolean> {\n const entityTriplet = `${entity.metadata.namespace}/${entity.kind}/${entity.metadata.name}`;\n const entityRootDir = this.legacyPathCasing\n ? entityTriplet\n : lowerCaseEntityTriplet(entityTriplet);\n\n return this.storageClient\n .getContainerClient(this.containerName)\n .getBlockBlobClient(`${entityRootDir}/index.html`)\n .exists();\n }\n\n protected async renameBlob(\n originalName: string,\n newName: string,\n removeOriginal = false,\n ): Promise<void> {\n const container = this.storageClient.getContainerClient(this.containerName);\n const blob = container.getBlobClient(newName);\n const { url } = container.getBlobClient(originalName);\n const response = await blob.beginCopyFromURL(url);\n await response.pollUntilDone();\n if (removeOriginal) {\n await container.deleteBlob(originalName);\n }\n }\n\n protected async renameBlobToLowerCase(\n originalPath: string,\n removeOriginal: boolean,\n ) {\n let newPath;\n try {\n newPath = lowerCaseEntityTripletInStoragePath(originalPath);\n } catch (e) {\n assertError(e);\n this.logger.warn(e.message);\n return;\n }\n\n if (originalPath === newPath) return;\n try {\n this.logger.debug(`Migrating ${originalPath}`);\n await this.renameBlob(originalPath, newPath, removeOriginal);\n } catch (e) {\n assertError(e);\n this.logger.warn(`Unable to migrate ${originalPath}: ${e.message}`);\n }\n }\n\n async migrateDocsCase({\n removeOriginal = false,\n concurrency = 25,\n }): Promise<void> {\n const promises = [];\n const limiter = limiterFactory(concurrency);\n const container = this.storageClient.getContainerClient(this.containerName);\n\n for await (const blob of container.listBlobsFlat()) {\n promises.push(\n limiter(\n this.renameBlobToLowerCase.bind(this),\n blob.name,\n removeOriginal,\n ),\n );\n }\n\n await Promise.all(promises);\n }\n\n protected async getAllBlobsFromContainer({\n prefix,\n maxPageSize,\n }: {\n prefix: string;\n maxPageSize: number;\n }): Promise<string[]> {\n const blobs: string[] = [];\n const container = this.storageClient.getContainerClient(this.containerName);\n\n let iterator = container.listBlobsFlat({ prefix }).byPage({ maxPageSize });\n let response = (await iterator.next()).value;\n\n do {\n for (const blob of response?.segment?.blobItems ?? []) {\n blobs.push(blob.name);\n }\n iterator = container\n .listBlobsFlat({ prefix })\n .byPage({ continuationToken: response.continuationToken, maxPageSize });\n response = (await iterator.next()).value;\n } while (response && response.continuationToken);\n\n return blobs;\n }\n}\n"],"names":["BlobServiceClient","StorageSharedKeyCredential","DefaultAzureCredential","assertError","getCloudPathForLocalPath","getFileTreeRecursively","bulkStorageOperation","path","getStaleFiles","lowerCaseEntityTriplet","JSON5","ForwardedError","lowerCaseEntityTripletInStoragePath","platformPath","getHeadersForFileExtension","limiterFactory"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/plugin-techdocs-node",
|
|
3
|
-
"version": "1.13.2
|
|
3
|
+
"version": "1.13.2",
|
|
4
4
|
"description": "Common node.js functionalities for TechDocs, to be shared between techdocs-backend plugin and techdocs-cli",
|
|
5
5
|
"backstage": {
|
|
6
6
|
"role": "node-library",
|
|
@@ -53,14 +53,14 @@
|
|
|
53
53
|
"@aws-sdk/types": "^3.347.0",
|
|
54
54
|
"@azure/identity": "^4.0.0",
|
|
55
55
|
"@azure/storage-blob": "^12.5.0",
|
|
56
|
-
"@backstage/backend-plugin-api": "1.
|
|
57
|
-
"@backstage/catalog-model": "1.7.3",
|
|
58
|
-
"@backstage/config": "1.3.2",
|
|
59
|
-
"@backstage/errors": "1.2.7",
|
|
60
|
-
"@backstage/integration": "1.16.3
|
|
61
|
-
"@backstage/integration-aws-node": "0.1.15",
|
|
62
|
-
"@backstage/plugin-search-common": "1.2.17",
|
|
63
|
-
"@backstage/plugin-techdocs-common": "0.1.0",
|
|
56
|
+
"@backstage/backend-plugin-api": "^1.3.0",
|
|
57
|
+
"@backstage/catalog-model": "^1.7.3",
|
|
58
|
+
"@backstage/config": "^1.3.2",
|
|
59
|
+
"@backstage/errors": "^1.2.7",
|
|
60
|
+
"@backstage/integration": "^1.16.3",
|
|
61
|
+
"@backstage/integration-aws-node": "^0.1.15",
|
|
62
|
+
"@backstage/plugin-search-common": "^1.2.17",
|
|
63
|
+
"@backstage/plugin-techdocs-common": "^0.1.0",
|
|
64
64
|
"@google-cloud/storage": "^7.0.0",
|
|
65
65
|
"@smithy/node-http-handler": "^3.0.0",
|
|
66
66
|
"@trendyol-js/openstack-swift-sdk": "^0.0.7",
|
|
@@ -78,8 +78,8 @@
|
|
|
78
78
|
"winston": "^3.2.1"
|
|
79
79
|
},
|
|
80
80
|
"devDependencies": {
|
|
81
|
-
"@backstage/backend-test-utils": "1.
|
|
82
|
-
"@backstage/cli": "0.32.0
|
|
81
|
+
"@backstage/backend-test-utils": "^1.4.0",
|
|
82
|
+
"@backstage/cli": "^0.32.0",
|
|
83
83
|
"@types/fs-extra": "^11.0.0",
|
|
84
84
|
"@types/js-yaml": "^4.0.0",
|
|
85
85
|
"@types/mime-types": "^2.1.0",
|
|
@@ -87,5 +87,12 @@
|
|
|
87
87
|
"@types/supertest": "^2.0.8",
|
|
88
88
|
"aws-sdk-client-mock": "^4.0.0",
|
|
89
89
|
"supertest": "^7.0.0"
|
|
90
|
+
},
|
|
91
|
+
"typesVersions": {
|
|
92
|
+
"*": {
|
|
93
|
+
"package.json": [
|
|
94
|
+
"package.json"
|
|
95
|
+
]
|
|
96
|
+
}
|
|
90
97
|
}
|
|
91
98
|
}
|