UNPKG

@azure-utils/storybooks

Version:

Utils to upload and manage Storybooks via Azure Functions and storage.

444 lines (440 loc) 16.3 kB
const require_chunk = require('./chunk-DWy1uDak.cjs'); const require_constants = require('./constants-94H7Co6A.cjs'); const require_shared = require('./shared-BSQDPNdH.cjs'); const require_projects = require('./projects-Dq7sJTc7.cjs'); const require_openapi_utils = require('./openapi-utils-CMVFCUk1.cjs'); const require_store = require('./store-CYxr095K.cjs'); const require_url_utils = require('./url-utils-Dy7KiQmB.cjs'); const require_builds_table = require('./builds-table-C0WHumRL.cjs'); const require_labels_table = require('./labels-table-C6Zj73wz.cjs'); const __azure_functions = require_chunk.__toESM(require("@azure/functions")); const zod = require_chunk.__toESM(require("zod")); //#region src/components/label-form.tsx var import_jsx_runtime$1 = require_chunk.__toESM(require_store.require_jsx_runtime()); async function LabelForm({ label, projectId }) { return /* @__PURE__ */ (0, import_jsx_runtime$1.jsxs)("form", { "hx-ext": "response-targets", "hx-patch": label ? require_store.urlBuilder.labelSlug(projectId, label.slug) : void 0, "hx-post": label ? void 0 : require_store.urlBuilder.allLabels(projectId), "hx-target-error": "#form-error", style: { maxWidth: "60ch" }, children: [ /* @__PURE__ */ (0, import_jsx_runtime$1.jsxs)("fieldset", { children: [ /* @__PURE__ */ (0, import_jsx_runtime$1.jsx)("legend", { children: "Details" }), label ? /* @__PURE__ */ (0, import_jsx_runtime$1.jsx)("input", { type: "hidden", name: "slug", value: label.slug }) : null, /* @__PURE__ */ (0, import_jsx_runtime$1.jsxs)("div", { class: "field", children: [/* @__PURE__ */ (0, import_jsx_runtime$1.jsx)("label", { for: "value", children: "Label" }), /* @__PURE__ */ (0, import_jsx_runtime$1.jsx)("input", { id: "value", name: "value", required: true, value: label?.value })] }) ] }), /* @__PURE__ */ (0, import_jsx_runtime$1.jsxs)("fieldset", { children: [ /* @__PURE__ */ (0, import_jsx_runtime$1.jsx)("legend", { children: "Type" }), /* @__PURE__ */ (0, import_jsx_runtime$1.jsx)("div", { style: { display: "grid", gridTemplateColumns: "repeat(3,1fr)", gap: "0.5rem" }, children: require_projects.labelTypes.map((type) => { const id = `type-${type}`; return /* @__PURE__ */ (0, import_jsx_runtime$1.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime$1.jsx)("input", { id, name: "type", type: "radio", required: true, value: type, checked: type === label?.type }), /* @__PURE__ */ (0, import_jsx_runtime$1.jsx)("label", { for: id, children: type })] }); }) }), /* @__PURE__ */ (0, import_jsx_runtime$1.jsx)("span", { class: "description", children: "Type of label defines behaviour of the label." }) ] }), /* @__PURE__ */ (0, import_jsx_runtime$1.jsxs)("div", { style: { display: "flex", gap: "1rem" }, children: [/* @__PURE__ */ (0, import_jsx_runtime$1.jsxs)("button", { type: "submit", children: [label ? "Update" : "Create", " Label"] }), /* @__PURE__ */ (0, import_jsx_runtime$1.jsx)("button", { type: "reset", children: "Reset" })] }), /* @__PURE__ */ (0, import_jsx_runtime$1.jsx)(require_store.ErrorMessage, { id: "form-error" }) ] }); } //#endregion //#region src/handlers/label-handlers.tsx var import_jsx_runtime = require_chunk.__toESM(require_store.require_jsx_runtime()); async function listLabels(request, context) { const { projectId = "" } = request.params; try { if (require_store.checkIsNewMode()) return require_store.responseHTML(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(require_store.DocumentLayout, { title: "Create Label", breadcrumbs: [{ label: projectId, href: require_store.urlBuilder.projectId(projectId) }, { label: "Labels", href: require_store.urlBuilder.allLabels(projectId) }], children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LabelForm, { projectId, label: void 0 }) })); const { connectionString } = require_store.getStore(); const labelModel = new require_projects.LabelModel(context, connectionString, projectId); const labels = await labelModel.list(); if (require_store.checkIsHTMLRequest()) return require_store.responseHTML(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(require_store.DocumentLayout, { title: "All Labels", breadcrumbs: [projectId], toolbar: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: require_store.urlBuilder.labelCreate(projectId), children: "+ Create" }), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(require_labels_table.LabelsTable, { labels, projectId, caption: `Labels (${labels.length})` }) })); return { status: 200, jsonBody: labels }; } catch (error) { return require_store.responseError(error, context); } } async function createLabel(request, context) { try { const { projectId = "" } = request.params; const { connectionString } = require_store.getStore(); const model = new require_projects.LabelModel(context, connectionString, projectId); if (!await model.projectModel.has(projectId)) return require_store.responseError(`The project '${projectId}' does not exist.`, context, 404); const contentType = request.headers.get("content-type"); if (!contentType) return require_store.responseError("Content-Type header is required", context, 400); if (!contentType.includes(require_constants.CONTENT_TYPES.FORM_ENCODED)) return require_store.responseError(`Invalid Content-Type, expected ${require_constants.CONTENT_TYPES.FORM_ENCODED}`, context, 415); const data = require_projects.LabelCreateSchema.parse(require_url_utils.urlSearchParamsToObject(await request.formData())); await model.create(data); const labelUrl = require_store.urlBuilder.labelSlug(projectId, require_projects.LabelModel.createSlug(data.value)); if (require_store.checkIsHTMLRequest() || require_store.checkIsHXRequest()) return require_store.responseRedirect(labelUrl, 303); return { status: 201, headers: { Location: labelUrl }, jsonBody: { data, links: { self: labelUrl } } }; } catch (error) { return require_store.responseError(error, context); } } async function getLabel(request, context) { const { projectId = "", labelSlug = "" } = request.params; try { const { connectionString } = require_store.getStore(); const labelModel = new require_projects.LabelModel(context, connectionString, projectId); const label = await labelModel.get(labelSlug); if (require_store.checkIsEditMode()) return require_store.responseHTML(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(require_store.DocumentLayout, { title: "Edit Label", breadcrumbs: [ { label: projectId, href: require_store.urlBuilder.projectId(projectId) }, { label: "Labels", href: require_store.urlBuilder.allLabels(projectId) }, { label: label.slug, href: require_store.urlBuilder.labelSlug(projectId, labelSlug) } ], children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LabelForm, { projectId, label }) })); const projectModel = labelModel.projectModel; const project = await projectModel.get(projectId); const builds = await projectModel.buildModel(projectId).list({ filter: `PartitionKey eq '${labelSlug}'` }); if (require_store.checkIsHTMLRequest()) return require_store.responseHTML(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(require_store.DocumentLayout, { title: `[${label.type}] ${label.value}`, breadcrumbs: [projectId, "Labels"], toolbar: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", gap: "1rem", alignItems: "center" }, children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: require_store.urlBuilder.labelSlugEdit(projectId, labelSlug), children: "Edit" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("form", { "hx-delete": request.url, "hx-confirm": "Are you sure about deleting the label?", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { children: "Delete" }) })] }), children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(require_builds_table.RawDataPreview, { data: label, summary: "Label details" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(require_builds_table.BuildTable, { caption: `Builds (${builds.length})`, builds, labels: void 0, project })] }) })); return { status: 202, jsonBody: { ...label, builds } }; } catch (error) { return require_store.responseError(error, context); } } async function updateLabel(request, context) { const { projectId = "", labelSlug = "" } = request.params; try { const { connectionString } = require_store.getStore(); const contentType = request.headers.get("content-type"); if (!contentType) return require_store.responseError("Content-Type header is required", context, 400); if (!contentType.includes(require_constants.CONTENT_TYPES.FORM_ENCODED)) return require_store.responseError(`Invalid Content-Type, expected ${require_constants.CONTENT_TYPES.FORM_ENCODED}`, context, 415); const data = require_projects.LabelUpdateSchema.partial().parse(require_url_utils.urlSearchParamsToObject(await request.formData())); const labelModel = new require_projects.LabelModel(context, connectionString, projectId); await labelModel.update(labelSlug, data); const labelUrl = require_store.urlBuilder.labelSlug(projectId, labelSlug); if (require_store.checkIsHTMLRequest() || require_store.checkIsHXRequest()) return require_store.responseRedirect(request.url, 303); return { status: 202, headers: { Location: labelUrl }, jsonBody: { data: await labelModel.get(labelSlug), links: { self: request.url } } }; } catch (error) { return require_store.responseError(error, context); } } async function deleteLabel(request, context) { const { projectId = "", labelSlug = "" } = request.params; try { const { connectionString } = require_store.getStore(); const labelModel = new require_projects.LabelModel(context, connectionString, projectId); await labelModel.delete(labelSlug); const labelsUrl = require_store.urlBuilder.allLabels(projectId); if (require_store.checkIsHTMLRequest() || require_store.checkIsHXRequest()) return require_store.responseRedirect(labelsUrl, 303); return { status: 204, headers: { Location: labelsUrl } }; } catch (error) { return require_store.responseError(error, context); } } async function getLabelLatestBuild(request, context) { const { projectId = "", labelSlug = "" } = request.params; context.log("Getting latest build for label '%s' in project '%s'...", labelSlug, projectId); try { const { connectionString } = require_store.getStore(); const labelModel = new require_projects.LabelModel(context, connectionString, projectId); const { buildSHA: latestBuildSHA } = await labelModel.get(labelSlug); if (!latestBuildSHA) return { status: 404, jsonBody: { error: "No builds found for this label." } }; return { status: 303, headers: { Location: require_store.urlBuilder.buildSHA(projectId, latestBuildSHA) } }; } catch (error) { return require_store.responseError(error, context); } } //#endregion //#region src/routers/labels-router.ts const TAG = require_openapi_utils.openAPITags.labels.name; function registerLabelsRouter(options) { const { authLevel, baseRoute, basePathParamsSchema, handlerWrapper, openAPIEnabled, serviceName } = options; __azure_functions.app.get(`${serviceName}-labels-list`, { authLevel, route: baseRoute, handler: handlerWrapper(listLabels, [{ resource: "label", action: "read" }, { resource: "ui", action: "read" }]) }); __azure_functions.app.post(`${serviceName}-label-create`, { authLevel, route: baseRoute, handler: handlerWrapper(createLabel, [{ resource: "label", action: "create" }]) }); const routeWithLabel = require_url_utils.joinUrl(baseRoute, "{labelSlug}"); __azure_functions.app.get(`${serviceName}-label-get`, { authLevel, route: routeWithLabel, handler: handlerWrapper(getLabel, [{ resource: "label", action: "read" }, { resource: "ui", action: "read" }]) }); __azure_functions.app.patch(`${serviceName}-label-update`, { authLevel, route: routeWithLabel, handler: handlerWrapper(updateLabel, [{ resource: "label", action: "update" }]) }); __azure_functions.app.deleteRequest(`${serviceName}-label-delete`, { authLevel, route: routeWithLabel, handler: handlerWrapper(deleteLabel, [{ resource: "label", action: "delete" }]) }); const routeWithLabelLatest = require_url_utils.joinUrl(routeWithLabel, "latest"); __azure_functions.app.get(`${serviceName}-label-latest`, { authLevel, route: routeWithLabelLatest, handler: handlerWrapper(getLabelLatestBuild, [{ resource: "label", action: "read" }]) }); if (openAPIEnabled) { const labelPathParameterSchema = basePathParamsSchema.extend({ labelSlug: require_shared.LabelSlugSchema }); require_openapi_utils.registerOpenAPIPath(baseRoute, { get: { tags: [TAG], summary: "List all labels for the project.", description: "Retrieves a list of labels.", requestParams: { path: basePathParamsSchema }, responses: { ...require_constants.commonErrorResponses, 200: { description: "A list of labels.", content: { [require_constants.CONTENT_TYPES.JSON]: { schema: require_projects.LabelSchema.array(), example: [{ slug: "label-slug", value: "label/slug" }] }, [require_constants.CONTENT_TYPES.HTML]: { example: "<!DOCTYPE html>" } } } } }, post: { tags: [TAG], summary: "Create a new label.", description: "Create a new label with slug and type.", requestParams: { path: basePathParamsSchema }, responses: { ...require_constants.commonErrorResponses, 202: { description: "Data about label", content: { [require_constants.CONTENT_TYPES.JSON]: { schema: require_projects.LabelSchema } } }, 303: { description: "Label created, redirecting...", headers: { Location: zod.default.url() } } } } }); require_openapi_utils.registerOpenAPIPath(routeWithLabel, { get: { tags: [TAG], summary: "Get label details", description: "Retrieves the details of a specific label and all builds associated with it.", requestParams: { path: labelPathParameterSchema }, responses: { ...require_constants.commonErrorResponses, 200: { description: "Label details retrieved successfully", content: { [require_constants.CONTENT_TYPES.JSON]: { schema: require_projects.LabelSchema }, [require_constants.CONTENT_TYPES.HTML]: { example: "<!DOCTYPE html>" } } }, 404: { description: "Matching label not found." } } }, delete: { tags: [TAG], summary: "Delete a label", description: "Deletes a specific label and builds associated with it.", requestParams: { path: labelPathParameterSchema }, responses: { ...require_constants.commonErrorResponses, 204: { description: "Label deleted successfully" }, 404: { description: "Matching label not found." } } } }); require_openapi_utils.registerOpenAPIPath(routeWithLabelLatest, { get: { tags: [TAG], summary: "Redirect to latest build for a label", description: "Redirects to the latest build associated with a specific label.", requestParams: { path: labelPathParameterSchema }, responses: { ...require_constants.commonErrorResponses, 308: { description: "Redirecting to latest build.", headers: { Location: { content: zod.default.string().meta({ description: "URL of the latest build" }) } } }, 404: { description: "Matching label or build not found." } } } }); } } //#endregion Object.defineProperty(exports, 'registerLabelsRouter', { enumerable: true, get: function () { return registerLabelsRouter; } });