@azure-utils/storybooks
Version:
Utils to upload and manage Storybooks via Azure Functions and storage.
87 lines (84 loc) • 3.78 kB
JavaScript
import { getStore, responseError, urlBuilder } from "./store-BL4RNiEp.mjs";
import { CACHE_CONTROL_PUBLIC_YEAR, commonErrorResponses } from "./constants-CsV1N9r4.mjs";
import { generateAzureStorageContainerName } from "./azure-storage-blob-Dj53y4ng.mjs";
import { BuildSHASchema, ProjectIdSchema } from "./shared-BAE3ceND.mjs";
import { openAPITags, registerOpenAPIPath } from "./openapi-utils-CAJ85ahl.mjs";
import { joinUrl } from "./url-utils-B9Pl4bQ7.mjs";
import { app } from "@azure/functions";
import z from "zod";
import { BlobServiceClient } from "@azure/storage-blob";
import path from "node:path";
import { Readable } from "node:stream";
//#region src/handlers/storybook-handler.tsx
async function serveStorybook(request, context) {
const { projectId = "", buildSHA = "", filepath = "" } = request.params;
const blobName = path.posix.join(buildSHA, filepath);
context.log("Serving SB (%s) - %s...", projectId, blobName);
const { connectionString } = getStore();
const blockBlobClient = BlobServiceClient.fromConnectionString(connectionString).getContainerClient(generateAzureStorageContainerName(projectId)).getBlockBlobClient(blobName);
if (!await blockBlobClient.exists()) return responseError(`File '${blobName}' not found.`, context, 404);
if (blobName.endsWith("index.html")) {
const buffer = await blockBlobClient.downloadToBuffer(0);
const bodyWithBackButton = buffer.toString("utf8").replace(`</body>`, `
<div><a id="view-all" href="${urlBuilder.allBuilds(projectId)}"
style="position: fixed; bottom: 0.5rem; left: 0.5rem; z-index: 9999; padding: 0.25rem 0.5rem; background-color: black; color: white; border-radius: 0.25rem; text-decoration: none; font-size: 1rem; font-face: sans-serif; font-weight: 400;">
← View all
</a></div></body>`);
return {
headers: {
"Cache-Control": CACHE_CONTROL_PUBLIC_YEAR,
"Content-Type": "text/html; charset=utf8",
"Content-Length": Buffer.byteLength(bodyWithBackButton).toString()
},
body: bodyWithBackButton,
status: 200
};
}
const downloadResponse = await blockBlobClient.download(0);
const headers = new Headers();
headers.set("Cache-Control", CACHE_CONTROL_PUBLIC_YEAR);
headers.set("Content-Type", downloadResponse.contentType || "application/octet-stream");
if (downloadResponse.contentLength) headers.set("Content-Length", downloadResponse.contentLength.toString());
if (downloadResponse.contentEncoding) headers.set("Content-Encoding", downloadResponse.contentEncoding);
return {
body: Readable.toWeb(downloadResponse.readableStreamBody),
headers,
status: 200
};
}
//#endregion
//#region src/routers/storybook-router.ts
const TAG = openAPITags.storybook.name;
function registerStorybookRouter(options) {
const { authLevel, baseRoute, basePathParamsSchema, handlerWrapper, openAPIEnabled, serviceName } = options;
const storybookRoute = joinUrl(baseRoute, "{projectId}", "{buildSHA}", "{**filepath}");
app.get(`${serviceName}-serve-storybook`, {
authLevel,
route: storybookRoute,
handler: handlerWrapper(serveStorybook, [{
resource: "build",
action: "read"
}])
});
if (openAPIEnabled) registerOpenAPIPath(storybookRoute, { get: {
tags: [TAG],
summary: "List all projects",
description: "Retrieves a list of projects.",
requestParams: { path: basePathParamsSchema.extend({
projectId: ProjectIdSchema,
buildSHA: BuildSHASchema,
"**filepath": z.string().meta({
description: "The path to the storybook files.",
example: "index.html"
})
}) },
responses: {
...commonErrorResponses,
200: { description: "Serve the file." },
404: { description: "File not found." }
}
} });
}
//#endregion
export { registerStorybookRouter };
//# sourceMappingURL=storybook-router-CnKx8NCO.mjs.map