chore: import upstream snapshot with attribution
Deploy (to testing) and Test Playground Preview Worker / Deploy Playground Preview Worker (testing) (push) Has been skipped
Deploy Workers Shared Staging / Deploy Workers Shared Staging (push) Failing after 0s
Prerelease / build (push) Has been skipped
Handle Changesets / Handle Changesets (push) Has been cancelled
Semgrep OSS scan / semgrep-oss (push) Has been cancelled
Deploy (to testing) and Test Playground Preview Worker / Deploy Playground Preview Worker (testing) (push) Has been skipped
Deploy Workers Shared Staging / Deploy Workers Shared Staging (push) Failing after 0s
Prerelease / build (push) Has been skipped
Handle Changesets / Handle Changesets (push) Has been cancelled
Semgrep OSS scan / semgrep-oss (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,164 @@
|
||||
import { relative } from "node:path";
|
||||
import {
|
||||
HEADERS_VERSION,
|
||||
PLACEHOLDER_REGEX,
|
||||
REDIRECTS_VERSION,
|
||||
SPLAT_REGEX,
|
||||
} from "./constants";
|
||||
import type {
|
||||
AssetConfig,
|
||||
MetadataHeaders,
|
||||
MetadataRedirects,
|
||||
MetadataStaticRedirects,
|
||||
} from "../types";
|
||||
import type { Logger, ParsedHeaders, ParsedRedirects } from "./types";
|
||||
|
||||
export function constructRedirects({
|
||||
redirects,
|
||||
redirectsFile,
|
||||
logger,
|
||||
}: {
|
||||
redirects?: ParsedRedirects;
|
||||
redirectsFile?: string;
|
||||
logger: Logger;
|
||||
}): Pick<AssetConfig, "redirects"> {
|
||||
if (!redirects) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const num_valid = redirects.rules.length;
|
||||
const num_invalid = redirects.invalid.length;
|
||||
|
||||
// exhaustive check, since we could not have parsed `redirects` out of
|
||||
// a non-existing redirects file
|
||||
const redirectsRelativePath = redirectsFile
|
||||
? relative(process.cwd(), redirectsFile)
|
||||
: "";
|
||||
|
||||
logger.log(
|
||||
`✨ Parsed ${num_valid} valid redirect rule${num_valid === 1 ? "" : "s"}.`
|
||||
);
|
||||
|
||||
if (num_invalid > 0) {
|
||||
let invalidRedirectRulesList = ``;
|
||||
|
||||
for (const { line, lineNumber, message } of redirects.invalid) {
|
||||
invalidRedirectRulesList += `▶︎ ${message}\n`;
|
||||
|
||||
if (line) {
|
||||
invalidRedirectRulesList += ` at ${redirectsRelativePath}${lineNumber ? `:${lineNumber}` : ""} | ${line}\n\n`;
|
||||
}
|
||||
}
|
||||
|
||||
logger.warn(
|
||||
`Found ${num_invalid} invalid redirect rule${num_invalid === 1 ? "" : "s"}:\n` +
|
||||
`${invalidRedirectRulesList}`
|
||||
);
|
||||
}
|
||||
|
||||
/* Better to return no Redirects object at all than one with empty rules */
|
||||
if (num_valid === 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const staticRedirects: MetadataStaticRedirects = {};
|
||||
const dynamicRedirects: MetadataRedirects = {};
|
||||
let canCreateStaticRule = true;
|
||||
for (const rule of redirects.rules) {
|
||||
if (!rule.from.match(SPLAT_REGEX) && !rule.from.match(PLACEHOLDER_REGEX)) {
|
||||
if (canCreateStaticRule) {
|
||||
staticRedirects[rule.from] = {
|
||||
status: rule.status,
|
||||
to: rule.to,
|
||||
lineNumber: rule.lineNumber,
|
||||
};
|
||||
continue;
|
||||
} else {
|
||||
logger.info(
|
||||
`The redirect rule ${rule.from} → ${rule.status} ${rule.to} could be made more performant by bringing it above any lines with splats or placeholders.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
dynamicRedirects[rule.from] = { status: rule.status, to: rule.to };
|
||||
canCreateStaticRule = false;
|
||||
}
|
||||
|
||||
return {
|
||||
redirects: {
|
||||
version: REDIRECTS_VERSION,
|
||||
staticRules: staticRedirects,
|
||||
rules: dynamicRedirects,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function constructHeaders({
|
||||
headers,
|
||||
headersFile,
|
||||
logger,
|
||||
}: {
|
||||
headers?: ParsedHeaders;
|
||||
headersFile?: string;
|
||||
logger: Logger;
|
||||
}): Pick<AssetConfig, "headers"> {
|
||||
if (!headers) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const num_valid = headers.rules.length;
|
||||
const num_invalid = headers.invalid.length;
|
||||
|
||||
// exhaustive check, since we could not have parsed `headers` out of
|
||||
// a non-existing headers file
|
||||
const headersRelativePath = headersFile
|
||||
? relative(process.cwd(), headersFile)
|
||||
: "";
|
||||
|
||||
logger.log(
|
||||
`✨ Parsed ${num_valid} valid header rule${num_valid === 1 ? "" : "s"}.`
|
||||
);
|
||||
|
||||
if (num_invalid > 0) {
|
||||
let invalidHeaderRulesList = ``;
|
||||
|
||||
for (const { line, lineNumber, message } of headers.invalid) {
|
||||
invalidHeaderRulesList += `▶︎ ${message}\n`;
|
||||
|
||||
if (line) {
|
||||
invalidHeaderRulesList += ` at ${headersRelativePath}${lineNumber ? `:${lineNumber}` : ""} | ${line}\n\n`;
|
||||
}
|
||||
}
|
||||
|
||||
logger.warn(
|
||||
`Found ${num_invalid} invalid header rule${num_invalid === 1 ? "" : "s"}:\n` +
|
||||
`${invalidHeaderRulesList}`
|
||||
);
|
||||
}
|
||||
|
||||
/* Better to return no Headers object at all than one with empty rules */
|
||||
if (num_valid === 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const rules: MetadataHeaders = {};
|
||||
for (const rule of headers.rules) {
|
||||
const configuredRule: MetadataHeaders[string] = {};
|
||||
|
||||
if (Object.keys(rule.headers).length) {
|
||||
configuredRule.set = rule.headers;
|
||||
}
|
||||
if (rule.unsetHeaders.length) {
|
||||
configuredRule.unset = rule.unsetHeaders;
|
||||
}
|
||||
|
||||
rules[rule.path] = configuredRule;
|
||||
}
|
||||
|
||||
return {
|
||||
headers: {
|
||||
version: HEADERS_VERSION,
|
||||
rules,
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user