You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
62 lines
2.1 KiB
62 lines
2.1 KiB
function trimSlashes(input: string): string {
|
|
return input.trim().replace(/^\/+|\/+$/g, "");
|
|
}
|
|
|
|
function hasParentSegment(input: string): boolean {
|
|
return input
|
|
.split("/")
|
|
.map((part) => part.trim())
|
|
.some((part) => part === "..");
|
|
}
|
|
|
|
function ensureRelativeDir(input: string, fallback: string, envName: string): string {
|
|
const value = input.trim();
|
|
if (!value) {
|
|
return fallback;
|
|
}
|
|
// 仅允许相对目录;绝对路径会绕过项目根约束。
|
|
if (value.startsWith("/")) {
|
|
throw new Error(`${envName} must be a relative directory path`);
|
|
}
|
|
return value;
|
|
}
|
|
|
|
function ensureSafeSubdir(input: string, fallback: string, envName: string): string {
|
|
const value = trimSlashes(input);
|
|
if (!value) {
|
|
return fallback;
|
|
}
|
|
if (hasParentSegment(value)) {
|
|
throw new Error(`${envName} must not contain ".." segments`);
|
|
}
|
|
return value;
|
|
}
|
|
|
|
/** 静态资源 URL 前缀固定为 `/static`,不允许通过环境变量覆写。 */
|
|
export const STATIC_PUBLIC_PREFIX = "/static";
|
|
|
|
/** 静态资源根目录,默认 `static` */
|
|
export const STATIC_DIR = ensureRelativeDir(process.env.STATIC_DIR ?? "static", "static", "STATIC_DIR");
|
|
|
|
/** 媒体上传子目录(相对 STATIC_DIR),默认 `media` */
|
|
export const MEDIA_UPLOAD_SUBDIR = ensureSafeSubdir(
|
|
process.env.MEDIA_UPLOAD_SUBDIR ?? "media",
|
|
"media",
|
|
"MEDIA_UPLOAD_SUBDIR",
|
|
);
|
|
|
|
/** 媒体上传目录(相对项目根),默认 `static/media` */
|
|
export const RELATIVE_ASSETS_DIR = `${STATIC_DIR}/${MEDIA_UPLOAD_SUBDIR}`;
|
|
|
|
/** 临时目录(相对项目根),默认 `.tmp` */
|
|
export const RELATIVE_TMP_DIR = ensureRelativeDir(process.env.TMP_DIR ?? ".tmp", ".tmp", "TMP_DIR");
|
|
|
|
/** 与 `media` 返回及静态路径一致,无前导 host */
|
|
export const POST_MEDIA_PUBLIC_PREFIX = `${STATIC_PUBLIC_PREFIX}/${MEDIA_UPLOAD_SUBDIR}/`;
|
|
|
|
/** 从未引用:created_at 起算;曾引用:dereferenced_at 起算 */
|
|
export const MEDIA_ORPHAN_GRACE_HOURS_NEVER_REF = 24;
|
|
export const MEDIA_ORPHAN_GRACE_HOURS_AFTER_DEREF = 24;
|
|
|
|
export const MEDIA_IMAGE_MAX_WIDTH_PX = 1920;
|
|
export const MEDIA_WEBP_QUALITY = 82;
|
|
|