34 lines
1.4 KiB
TypeScript
34 lines
1.4 KiB
TypeScript
import { createHash } from "node:crypto";
|
|
import type { PluginListItem } from "../services/.server/PluginLifecycleService";
|
|
import { getPluginConsentRequirements } from "./pluginConsentRequirements";
|
|
|
|
export function createCapabilityReviewDigest(item: Pick<PluginListItem, "pluginId" | "version" | "manifest">, capabilityNames: ReadonlyArray<string>) {
|
|
const selectedCapabilities = new Set(capabilityNames);
|
|
const reviewPayload = {
|
|
pluginId: item.pluginId,
|
|
version: item.version,
|
|
capabilities: getPluginConsentRequirements(item.manifest)
|
|
.filter((requirement) => selectedCapabilities.has(requirement.name))
|
|
.map((requirement) => ({
|
|
name: requirement.name,
|
|
scope: requirement.scope ?? null,
|
|
kind: requirement.kind,
|
|
}))
|
|
.sort((left, right) => left.name.localeCompare(right.name)),
|
|
};
|
|
return createHash("sha256").update(stableJsonStringify(reviewPayload)).digest("base64url");
|
|
}
|
|
|
|
function stableJsonStringify(value: unknown): string {
|
|
if (Array.isArray(value)) {
|
|
return `[${value.map((item) => stableJsonStringify(item)).join(",")}]`;
|
|
}
|
|
if (value && typeof value === "object") {
|
|
return `{${Object.entries(value as Record<string, unknown>)
|
|
.sort(([left], [right]) => left.localeCompare(right))
|
|
.map(([key, nestedValue]) => `${JSON.stringify(key)}:${stableJsonStringify(nestedValue)}`)
|
|
.join(",")}}`;
|
|
}
|
|
return JSON.stringify(value);
|
|
}
|