paperclip/tests/runner-e2e/history-destination.ts

61 lines
1.5 KiB
TypeScript

export interface RunnerE2EHistoryPublicDestination {
prefix: string;
publicBaseUrl: string;
}
export function validateHistoryPublicDestination(input: {
prefix: string;
publicBaseUrl: string;
}): RunnerE2EHistoryPublicDestination {
const prefix = input.prefix.replace(/^\/+|\/+$/g, "");
const segments = prefix.split("/");
if (
!prefix ||
segments.some(
(segment) =>
!segment ||
segment === "." ||
segment === ".." ||
!/^[A-Za-z0-9._~-]+$/.test(segment),
)
) {
throw new Error(
"RUNNER_E2E_HISTORY_PREFIX must be a safe non-empty key prefix",
);
}
const publicUrl = new URL(input.publicBaseUrl);
if (
publicUrl.protocol !== "https:" ||
publicUrl.username ||
publicUrl.password ||
publicUrl.search ||
publicUrl.hash
) {
throw new Error(
"RUNNER_E2E_HISTORY_PUBLIC_BASE_URL must be a credential-free HTTPS URL",
);
}
return {
prefix,
publicBaseUrl: publicUrl.href.replace(/\/+$/, ""),
};
}
export function validateHistoryDestination(input: {
bucket: string;
prefix: string;
publicBaseUrl: string;
}) {
if (!/^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/.test(input.bucket)) {
throw new Error("RUNNER_E2E_HISTORY_S3_BUCKET is not a valid bucket name");
}
return validateHistoryPublicDestination(input);
}
export function runnerE2ECampaignPublicUrl(
destination: RunnerE2EHistoryPublicDestination,
campaignId: string,
) {
return `${destination.publicBaseUrl}/${destination.prefix}/campaigns/${encodeURIComponent(campaignId)}/index.html`;
}