@azure-utils/storybooks
Version:
Utils to upload and manage Storybooks via Azure Functions and storage.
444 lines (440 loc) • 16.3 kB
JavaScript
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;
}
});