{"version":3,"file":"storybook-router-CnKx8NCO.mjs","names":["request: HttpRequest","context: InvocationContext","options: RouterOptions"],"sources":["../src/handlers/storybook-handler.tsx","../src/routers/storybook-router.ts"],"sourcesContent":["import type {\n  HttpRequest,\n  HttpResponseInit,\n  InvocationContext,\n} from \"@azure/functions\";\nimport { BlobServiceClient } from \"@azure/storage-blob\";\nimport path from \"node:path\";\nimport { generateAzureStorageContainerName } from \"../utils/azure-storage-blob\";\nimport { responseError } from \"../utils/response-utils\";\nimport { CACHE_CONTROL_PUBLIC_YEAR } from \"../utils/constants\";\nimport { Readable } from \"node:stream\";\nimport { getStore } from \"../utils/store\";\nimport { urlBuilder } from \"../utils/url-builder\";\n\nexport async function serveStorybook(\n  request: HttpRequest,\n  context: InvocationContext\n): Promise<HttpResponseInit> {\n  const { projectId = \"\", buildSHA = \"\", filepath = \"\" } = request.params;\n  const blobName = path.posix.join(buildSHA, filepath);\n  context.log(\"Serving SB (%s) - %s...\", projectId, blobName);\n\n  const { connectionString } = getStore();\n  const blockBlobClient = BlobServiceClient.fromConnectionString(\n    connectionString\n  )\n    .getContainerClient(generateAzureStorageContainerName(projectId))\n    .getBlockBlobClient(blobName);\n\n  if (!(await blockBlobClient.exists())) {\n    return responseError(`File '${blobName}' not found.`, context, 404);\n  }\n\n  if (blobName.endsWith(\"index.html\")) {\n    const buffer = await blockBlobClient.downloadToBuffer(0);\n    // Add a back button to the bottom of the page\n    const bodyWithBackButton = buffer.toString(\"utf8\").replace(\n      `</body>`,\n      `\n      <div><a id=\"view-all\" href=\"${urlBuilder.allBuilds(projectId)}\"\n        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;\">\n        ← View all\n      </a></div></body>`\n    );\n\n    return {\n      headers: {\n        \"Cache-Control\": CACHE_CONTROL_PUBLIC_YEAR,\n        \"Content-Type\": \"text/html; charset=utf8\",\n        \"Content-Length\": Buffer.byteLength(bodyWithBackButton).toString(),\n      },\n      body: bodyWithBackButton,\n      status: 200,\n    };\n  }\n\n  // For all other files, we stream the blob and return it\n  const downloadResponse = await blockBlobClient.download(0);\n\n  const headers = new Headers();\n  headers.set(\"Cache-Control\", CACHE_CONTROL_PUBLIC_YEAR);\n  headers.set(\n    \"Content-Type\",\n    downloadResponse.contentType || \"application/octet-stream\"\n  );\n  if (downloadResponse.contentLength) {\n    headers.set(\"Content-Length\", downloadResponse.contentLength.toString());\n  }\n  if (downloadResponse.contentEncoding) {\n    headers.set(\"Content-Encoding\", downloadResponse.contentEncoding);\n  }\n\n  return {\n    body: Readable.toWeb(downloadResponse.readableStreamBody as Readable),\n    headers,\n    status: 200,\n  };\n}\n","import { app } from \"@azure/functions\";\nimport { commonErrorResponses } from \"../utils/constants\";\nimport { openAPITags, registerOpenAPIPath } from \"../utils/openapi-utils\";\nimport type { RouterOptions } from \"../utils/types\";\nimport z from \"zod\";\nimport { joinUrl } from \"../utils/url-utils\";\nimport { serveStorybook } from \"../handlers/storybook-handler\";\nimport { BuildSHASchema, ProjectIdSchema } from \"../models/shared\";\n\nconst TAG = openAPITags.storybook.name;\n\nexport function registerStorybookRouter(options: RouterOptions) {\n  const {\n    authLevel,\n    baseRoute,\n    basePathParamsSchema,\n    handlerWrapper,\n    openAPIEnabled,\n    serviceName,\n  } = options;\n\n  const storybookRoute = joinUrl(\n    baseRoute,\n    \"{projectId}\",\n    \"{buildSHA}\",\n    \"{**filepath}\"\n  );\n\n  app.get(`${serviceName}-serve-storybook`, {\n    authLevel,\n    route: storybookRoute,\n    handler: handlerWrapper(serveStorybook, [\n      { resource: \"build\", action: \"read\" },\n    ]),\n  });\n\n  if (openAPIEnabled) {\n    registerOpenAPIPath(storybookRoute, {\n      get: {\n        tags: [TAG],\n        summary: \"List all projects\",\n        description: \"Retrieves a list of projects.\",\n        requestParams: {\n          path: basePathParamsSchema.extend({\n            projectId: ProjectIdSchema,\n            buildSHA: BuildSHASchema,\n            \"**filepath\": z.string().meta({\n              description: \"The path to the storybook files.\",\n              example: \"index.html\",\n            }),\n          }),\n        },\n        responses: {\n          ...commonErrorResponses,\n          200: { description: \"Serve the file.\" },\n          404: { description: \"File not found.\" },\n        },\n      },\n    });\n  }\n}\n"],"mappings":";;;;;;;;;;;;;AAcA,eAAsB,eACpBA,SACAC,SAC2B;CAC3B,MAAM,EAAE,YAAY,IAAI,WAAW,IAAI,WAAW,IAAI,GAAG,QAAQ;CACjE,MAAM,WAAW,KAAK,MAAM,KAAK,UAAU,SAAS;CACpD,QAAQ,IAAI,2BAA2B,WAAW,SAAS;CAE3D,MAAM,EAAE,kBAAkB,GAAG,UAAU;CACvC,MAAM,kBAAkB,kBAAkB,qBACxC,iBACD,CACE,mBAAmB,kCAAkC,UAAU,CAAC,CAChE,mBAAmB,SAAS;AAE/B,KAAI,CAAE,MAAM,gBAAgB,QAAQ,CAClC,QAAO,cAAc,CAAC,MAAM,EAAE,SAAS,YAAY,CAAC,EAAE,SAAS,IAAI;AAGrE,KAAI,SAAS,SAAS,aAAa,EAAE;EACnC,MAAM,SAAS,MAAM,gBAAgB,iBAAiB,EAAE;EAExD,MAAM,qBAAqB,OAAO,SAAS,OAAO,CAAC,QACjD,CAAC,OAAO,CAAC,EACT,CAAC;kCAC2B,EAAE,WAAW,UAAU,UAAU,CAAC;;;uBAG7C,CAAC,CACnB;AAED,SAAO;GACL,SAAS;IACP,iBAAiB;IACjB,gBAAgB;IAChB,kBAAkB,OAAO,WAAW,mBAAmB,CAAC,UAAU;GACnE;GACD,MAAM;GACN,QAAQ;EACT;CACF;CAGD,MAAM,mBAAmB,MAAM,gBAAgB,SAAS,EAAE;CAE1D,MAAM,UAAU,IAAI;CACpB,QAAQ,IAAI,iBAAiB,0BAA0B;CACvD,QAAQ,IACN,gBACA,iBAAiB,eAAe,2BACjC;AACD,KAAI,iBAAiB,eACnB,QAAQ,IAAI,kBAAkB,iBAAiB,cAAc,UAAU,CAAC;AAE1E,KAAI,iBAAiB,iBACnB,QAAQ,IAAI,oBAAoB,iBAAiB,gBAAgB;AAGnE,QAAO;EACL,MAAM,SAAS,MAAM,iBAAiB,mBAA+B;EACrE;EACA,QAAQ;CACT;AACF;;;;ACpED,MAAM,MAAM,YAAY,UAAU;AAElC,SAAgB,wBAAwBC,SAAwB;CAC9D,MAAM,EACJ,WACA,WACA,sBACA,gBACA,gBACA,aACD,GAAG;CAEJ,MAAM,iBAAiB,QACrB,WACA,eACA,cACA,eACD;CAED,IAAI,IAAI,GAAG,YAAY,gBAAgB,CAAC,EAAE;EACxC;EACA,OAAO;EACP,SAAS,eAAe,gBAAgB,CACtC;GAAE,UAAU;GAAS,QAAQ;EAAQ,CACtC,EAAC;CACH,EAAC;AAEF,KAAI,gBACF,oBAAoB,gBAAgB,EAClC,KAAK;EACH,MAAM,CAAC,GAAI;EACX,SAAS;EACT,aAAa;EACb,eAAe,EACb,MAAM,qBAAqB,OAAO;GAChC,WAAW;GACX,UAAU;GACV,cAAc,EAAE,QAAQ,CAAC,KAAK;IAC5B,aAAa;IACb,SAAS;GACV,EAAC;EACH,EAAC,CACH;EACD,WAAW;GACT,GAAG;GACH,KAAK,EAAE,aAAa,kBAAmB;GACvC,KAAK,EAAE,aAAa,kBAAmB;EACxC;CACF,EACF,EAAC;AAEL"}