@azure-utils/storybooks
Version:
Utils to upload and manage Storybooks via Azure Functions and storage.
1 lines • 21.1 kB
Source Map (JSON)
{"version":3,"file":"builds-router-BvRICvOx.mjs","names":["request: HttpRequest","context: InvocationContext","options: RouterOptions"],"sources":["../src/components/build-form.tsx","../src/handlers/build-handlers.tsx","../src/routers/builds-router.ts"],"sourcesContent":["import { CONTENT_TYPES } from \"../utils/constants\";\nimport { urlBuilder } from \"../utils/url-builder\";\nimport { ErrorMessage } from \"./error-message\";\n\nexport interface BuildFormProps {\n projectId: string;\n}\n\nexport async function BuildForm({ projectId }: BuildFormProps) {\n return (\n <form\n hx-ext=\"response-targets\"\n hx-post={urlBuilder.allBuilds(projectId)}\n hx-target-error=\"#form-error\"\n style={{ maxWidth: \"60ch\" }}\n enctype={CONTENT_TYPES.FORM_MULTIPART}\n >\n <fieldset>\n <legend>Details</legend>\n\n <div class=\"field\">\n <label for=\"sha\">SHA</label>\n <input id=\"sha\" name=\"sha\" required />\n </div>\n\n <div class=\"field\">\n <label for=\"message\">Message</label>\n <input id=\"message\" name=\"message\" />\n </div>\n\n <div class=\"field\">\n <label for=\"zipFile\">Zip file</label>\n <input\n id=\"zipFile\"\n name=\"zipFile\"\n type=\"file\"\n accept={CONTENT_TYPES.ZIP}\n required\n />\n </div>\n </fieldset>\n\n <fieldset>\n <legend>Author</legend>\n\n <div class=\"field\">\n <label for=\"authorName\">Name</label>\n <input id=\"authorName\" name=\"authorName\" required />\n </div>\n <div class=\"field\">\n <label for=\"authorEmail\">Email</label>\n <input id=\"authorEmail\" name=\"authorEmail\" required />\n </div>\n </fieldset>\n\n <fieldset>\n <legend>Labels</legend>\n\n {Array.from({ length: 4 }).map((_, i) => {\n const id = `label-${i}`;\n return (\n <div class=\"field\">\n <label for={id}>Label {i + 1}</label>\n <input id={id} name=\"labels\" required={i === 0} />\n {i === 0 ? <span class=\"description\">Required</span> : null}\n </div>\n );\n })}\n </fieldset>\n\n <div style={{ display: \"flex\", gap: \"1rem\" }}>\n <button type=\"submit\">Upload build</button>\n <button type=\"reset\">Reset</button>\n </div>\n\n <ErrorMessage id=\"form-error\" />\n </form>\n );\n}\n","import type {\n HttpRequest,\n HttpResponseInit,\n InvocationContext,\n} from \"@azure/functions\";\nimport {\n responseError,\n responseHTML,\n responseRedirect,\n} from \"../utils/response-utils\";\nimport { DocumentLayout } from \"../components/layout\";\nimport { RawDataPreview } from \"../components/raw-data\";\nimport { getStore } from \"../utils/store\";\nimport { urlSearchParamsToObject } from \"../utils/url-utils\";\nimport { BuildTable } from \"../components/builds-table\";\nimport { validateBuildUploadZipBody } from \"../utils/validators\";\nimport { uploadZipWithDecompressed } from \"../utils/upload-utils\";\nimport {\n BuildModel,\n BuildUploadFormSchema,\n BuildUploadSchema,\n} from \"../models/builds\";\nimport { urlBuilder } from \"../utils/url-builder\";\nimport {\n checkIsHTMLRequest,\n checkIsHXRequest,\n checkIsNewMode,\n} from \"../utils/request-utils\";\nimport { BuildForm } from \"../components/build-form\";\nimport { CONTENT_TYPES, QUERY_PARAMS } from \"../utils/constants\";\n\nexport async function listBuilds(\n request: HttpRequest,\n context: InvocationContext\n): Promise<HttpResponseInit> {\n const { projectId = \"\" } = request.params;\n\n try {\n if (checkIsNewMode()) {\n return responseHTML(\n <DocumentLayout\n title=\"Upload Build\"\n breadcrumbs={[\n { label: projectId, href: urlBuilder.projectId(projectId) },\n { label: \"Builds\", href: urlBuilder.allBuilds(projectId) },\n ]}\n >\n <BuildForm projectId={projectId} />\n </DocumentLayout>\n );\n }\n\n const { connectionString } = getStore();\n const buildModel = new BuildModel(context, connectionString, projectId);\n const builds = await buildModel.list();\n\n if (checkIsHTMLRequest()) {\n const projectModel = buildModel.projectModel;\n const project = await projectModel.get(projectId);\n const labels = await projectModel.labelModel(projectId).list();\n\n return responseHTML(\n <DocumentLayout\n title=\"All Builds\"\n breadcrumbs={[projectId]}\n toolbar={<a href={urlBuilder.buildUpload(projectId)}>Upload</a>}\n >\n <BuildTable\n builds={builds}\n labels={labels}\n project={project}\n caption={`Builds (${builds.length})`}\n />\n </DocumentLayout>\n );\n }\n\n return { status: 200, jsonBody: builds };\n } catch (error) {\n return responseError(error, context);\n }\n}\n\nexport async function getBuild(\n request: HttpRequest,\n context: InvocationContext\n): Promise<HttpResponseInit> {\n const { projectId = \"\", buildSHA = \"\" } = request.params;\n const labelSlug = request.query.get(QUERY_PARAMS.labelSlug) || undefined;\n\n try {\n const { connectionString } = getStore();\n const buildModel = new BuildModel(context, connectionString, projectId);\n const build = await buildModel.get(buildSHA, labelSlug);\n\n if (checkIsHTMLRequest()) {\n return responseHTML(\n <DocumentLayout\n breadcrumbs={[projectId, \"Builds\"]}\n title={\n build.message\n ? `[${build.sha.slice(0, 7)}] ${build.message}`\n : buildSHA.slice(0, 7)\n }\n toolbar={\n <div style={{ display: \"flex\", gap: \"1rem\", alignItems: \"center\" }}>\n <form\n hx-delete={request.url}\n hx-confirm=\"Are you sure about deleting the build?\"\n >\n <button>Delete</button>\n </form>\n </div>\n }\n >\n <>\n <RawDataPreview data={build} summary={\"Build details\"} open />\n <div style={{ marginTop: \"1rem\", display: \"flex\", gap: \"1rem\" }}>\n <a\n href={urlBuilder.storybookIndexHtml(projectId, buildSHA)}\n target=\"_blank\"\n >\n View Storybook\n </a>\n <a\n href={urlBuilder.storybookTestReport(projectId, buildSHA)}\n target=\"_blank\"\n >\n View Test Report\n </a>\n <a\n href={urlBuilder.storybookCoverage(projectId, buildSHA)}\n target=\"_blank\"\n >\n View Coverage\n </a>\n <a\n href={urlBuilder.storybookZip(projectId, buildSHA)}\n download={`storybook-${projectId}-${buildSHA}.zip`}\n target=\"_blank\"\n >\n Download Storybook\n </a>\n </div>\n </>\n </DocumentLayout>\n );\n }\n\n return { status: 200, jsonBody: build };\n } catch (error) {\n return responseError(error, context);\n }\n}\n\nexport async function deleteBuild(\n request: HttpRequest,\n context: InvocationContext\n): Promise<HttpResponseInit> {\n const { projectId = \"\", buildSHA = \"\" } = request.params;\n\n try {\n const { connectionString } = getStore();\n const buildModel = new BuildModel(context, connectionString, projectId);\n await buildModel.delete(buildSHA);\n\n const buildsUrl = urlBuilder.allBuilds(projectId);\n if (checkIsHTMLRequest() || checkIsHXRequest()) {\n return responseRedirect(buildsUrl, 303);\n }\n\n return { status: 204, headers: { Location: buildsUrl } };\n } catch (error) {\n return responseError(error, context);\n }\n}\n\nexport async function uploadBuild(\n request: HttpRequest,\n context: InvocationContext\n): Promise<HttpResponseInit> {\n try {\n const { projectId = \"\" } = request.params;\n const { connectionString } = getStore();\n\n const buildModel = new BuildModel(context, connectionString, projectId);\n\n if (!(await buildModel.projectModel.has(projectId))) {\n return responseError(\n `The project '${projectId}' does not exist.`,\n context,\n 404\n );\n }\n\n const contentType = request.headers.get(\"content-type\");\n if (contentType?.includes(CONTENT_TYPES.ZIP)) {\n const buildUploadData = BuildUploadSchema.parse(\n urlSearchParamsToObject(request.query)\n );\n const bodyValidationResponse = validateBuildUploadZipBody(\n request,\n context\n );\n if (bodyValidationResponse) {\n return bodyValidationResponse;\n }\n const uploadResponse = await uploadZipWithDecompressed(\n projectId,\n buildUploadData.sha\n );\n if (uploadResponse) {\n return uploadResponse;\n }\n await buildModel.create(buildUploadData);\n\n const buildUrl = urlBuilder.buildSHA(projectId, buildUploadData.sha);\n if (checkIsHTMLRequest() || checkIsHXRequest()) {\n return responseRedirect(buildUrl, 303);\n }\n\n return { status: 202 };\n }\n\n if (contentType?.includes(CONTENT_TYPES.FORM_MULTIPART)) {\n const { zipFile, ...buildUploadData } = BuildUploadFormSchema.parse(\n urlSearchParamsToObject(await request.formData())\n );\n const uploadResponse = await uploadZipWithDecompressed(\n projectId,\n buildUploadData.sha,\n zipFile\n );\n if (uploadResponse) {\n return uploadResponse;\n }\n await buildModel.create(buildUploadData);\n\n const buildUrl = urlBuilder.buildSHA(projectId, buildUploadData.sha);\n if (checkIsHTMLRequest() || checkIsHXRequest()) {\n return responseRedirect(buildUrl, 303);\n }\n\n return { status: 202 };\n }\n\n return responseError(\n `Invalid content type, expected ${CONTENT_TYPES.ZIP} or ${CONTENT_TYPES.FORM_MULTIPART}.`,\n context,\n 415\n );\n } catch (error) {\n return responseError(error, context);\n }\n}\n","import { app } from \"@azure/functions\";\nimport { commonErrorResponses, CONTENT_TYPES } from \"../utils/constants\";\nimport { openAPITags, registerOpenAPIPath } from \"../utils/openapi-utils\";\nimport type { RouterOptions } from \"../utils/types\";\nimport { joinUrl } from \"../utils/url-utils\";\nimport * as handlers from \"../handlers/build-handlers\";\nimport { BuildSHASchema } from \"../models/shared\";\nimport { BuildSchema, BuildUploadSchema } from \"../models/builds\";\n\nconst TAG = openAPITags.builds.name;\n\nexport function registerBuildsRouter(options: RouterOptions) {\n const {\n authLevel,\n baseRoute,\n basePathParamsSchema,\n handlerWrapper,\n openAPIEnabled,\n serviceName,\n } = options;\n const routeWithBuildSHA = joinUrl(baseRoute, \"{buildSHA}\");\n\n app.get(`${serviceName}-builds-list`, {\n authLevel,\n route: baseRoute,\n handler: handlerWrapper(handlers.listBuilds, [\n { resource: \"build\", action: \"read\" },\n { resource: \"ui\", action: \"read\" },\n ]),\n });\n app.post(`${serviceName}-build-upload`, {\n authLevel,\n route: baseRoute,\n handler: handlerWrapper(handlers.uploadBuild, [\n { resource: \"build\", action: \"create\" },\n ]),\n });\n app.get(`${serviceName}-build-get`, {\n authLevel,\n route: routeWithBuildSHA,\n handler: handlerWrapper(handlers.getBuild, [\n { resource: \"build\", action: \"read\" },\n { resource: \"ui\", action: \"read\" },\n ]),\n });\n app.deleteRequest(`${serviceName}-build-delete`, {\n authLevel,\n route: routeWithBuildSHA,\n handler: handlerWrapper(handlers.deleteBuild, [\n { resource: \"build\", action: \"delete\" },\n ]),\n });\n\n if (openAPIEnabled) {\n const buildPathParameterSchema = basePathParamsSchema.extend({\n buildSHA: BuildSHASchema,\n });\n\n registerOpenAPIPath(baseRoute, {\n get: {\n tags: [TAG],\n summary: \"List all builds for the project.\",\n description: \"Retrieves a list of builds.\",\n requestParams: { path: basePathParamsSchema },\n responses: {\n ...commonErrorResponses,\n 200: {\n description: \"A list of builds.\",\n content: {\n [CONTENT_TYPES.JSON]: {\n schema: BuildSchema.array(),\n example: [{ project: \"project-id\", sha: \"s123s14\" }],\n },\n [CONTENT_TYPES.HTML]: { example: \"<!DOCTYPE html>\" },\n },\n },\n },\n },\n post: {\n tags: [TAG],\n summary: \"Upload a new build\",\n description: \"Uploads a new build with the provided metadata.\",\n requestParams: {\n path: basePathParamsSchema,\n query: BuildUploadSchema,\n },\n requestBody: {\n required: true,\n description: \"Compressed zip containing storybook and test results.\",\n content: {\n [CONTENT_TYPES.ZIP]: {\n schema: { type: \"string\", format: \"binary\" },\n example: \"storybook.zip\",\n },\n },\n },\n responses: {\n ...commonErrorResponses,\n 202: { description: \"Build uploaded successfully\" },\n },\n },\n });\n\n registerOpenAPIPath(routeWithBuildSHA, {\n get: {\n tags: [TAG],\n summary: \"Get build details\",\n description: \"Retrieves the details of a specific build.\",\n requestParams: { path: buildPathParameterSchema },\n responses: {\n ...commonErrorResponses,\n 200: {\n description: \"Build details retrieved successfully\",\n content: {\n [CONTENT_TYPES.JSON]: {\n schema: BuildSchema,\n },\n [CONTENT_TYPES.HTML]: { example: \"<!DOCTYPE html>\" },\n },\n },\n 404: { description: \"Matching build not found.\" },\n },\n },\n delete: {\n tags: [TAG],\n summary: \"Delete a build\",\n description: \"Deletes a specific build.\",\n requestParams: { path: buildPathParameterSchema },\n responses: {\n ...commonErrorResponses,\n 204: { description: \"Build deleted successfully\" },\n 404: { description: \"Matching build not found.\" },\n },\n },\n });\n }\n}\n"],"mappings":"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"}