[Snow Team] Merge config-fixer's work with conflict resolution

This commit is contained in:
yml
2026-05-21 23:20:40 +08:00
2 changed files with 93 additions and 48 deletions
+42 -12
View File
@@ -5,11 +5,21 @@ import type {
AdminDefaultUser, AdminDefaultUser,
RuntimeConfig, RuntimeConfig,
} from "../types/runtime-config.js"; } from "../types/runtime-config.js";
import { parseBoolean, parseInteger, parseJsonArray } from "./runtime-env.js"; import {
parseBoolean,
parseInteger,
parseJsonArray,
parseCommaSeparatedStrings,
} from "./runtime-env.js";
import { deepMerge } from "./runtime-merge.js"; import { deepMerge } from "./runtime-merge.js";
type RuntimeConfigPath = readonly [string, ...string[]]; type RuntimeConfigPath = readonly [string, ...string[]];
type RuntimeConfigValue = string | number | boolean | AdminDefaultUser[]; type RuntimeConfigValue =
| string
| number
| boolean
| AdminDefaultUser[]
| string[];
type RuntimeEnv = Record<string, string | undefined>; type RuntimeEnv = Record<string, string | undefined>;
type EnvOverride = { type EnvOverride = {
@@ -347,31 +357,51 @@ function booleanEnv(env: string, configPath: RuntimeConfigPath): EnvOverride {
}; };
} }
function adminUsersJsonEnv(env: string, configPath: RuntimeConfigPath): EnvOverride { function adminUsersJsonEnv(
env: string,
configPath: RuntimeConfigPath
): EnvOverride {
return { return {
env, env,
path: configPath, path: configPath,
read(rawValue) { read(rawValue) {
return parseJsonArray<AdminDefaultUser>(rawValue) return parseJsonArray<AdminDefaultUser>(rawValue);
}, },
} };
} }
function corsOriginsEnv(env: string, configPath: RuntimeConfigPath): EnvOverride { function stringArrayEnv(
env: string,
configPath: RuntimeConfigPath
): EnvOverride {
return {
env,
path: configPath,
read: parseCommaSeparatedStrings,
};
}
function corsOriginsEnv(
env: string,
configPath: RuntimeConfigPath
): EnvOverride {
return { return {
env, env,
path: configPath, path: configPath,
read(rawValue) { read(rawValue) {
const value = parseString(rawValue) const value = parseString(rawValue);
if (value === null) { if (value === null) {
return null return null;
} }
if (value.trim() === '*') { if (value.trim() === "*") {
return ['*'] return ["*"];
} }
return value.split(',').map((s) => s.trim()).filter(Boolean) return value
.split(",")
.map((s) => s.trim())
.filter(Boolean);
}, },
} };
} }
function parseString(rawValue: unknown): string | null { function parseString(rawValue: unknown): string | null {
+51 -36
View File
@@ -1,98 +1,113 @@
import fs from 'node:fs' import fs from "node:fs";
import process from 'node:process' import process from "node:process";
export function loadEnvFiles(filePaths: string[]): void { export function loadEnvFiles(filePaths: string[]): void {
for (const filePath of filePaths) { for (const filePath of filePaths) {
loadEnvFile(filePath) loadEnvFile(filePath);
} }
} }
function loadEnvFile(filePath: string): void { function loadEnvFile(filePath: string): void {
if (!fs.existsSync(filePath)) { if (!fs.existsSync(filePath)) {
return return;
} }
const rawText = fs.readFileSync(filePath, 'utf8') const rawText = fs.readFileSync(filePath, "utf8");
const lines = rawText.split(/\r?\n/) const lines = rawText.split(/\r?\n/);
for (const rawLine of lines) { for (const rawLine of lines) {
const line = rawLine.trim() const line = rawLine.trim();
if (!line || line.startsWith('#')) { if (!line || line.startsWith("#")) {
continue continue;
} }
const separatorIndex = line.indexOf('=') const separatorIndex = line.indexOf("=");
if (separatorIndex <= 0) { if (separatorIndex <= 0) {
continue continue;
} }
const key = line.slice(0, separatorIndex).trim() const key = line.slice(0, separatorIndex).trim();
if (!key || key in process.env) { if (!key || key in process.env) {
continue continue;
} }
process.env[key] = parseEnvValue(line.slice(separatorIndex + 1)) process.env[key] = parseEnvValue(line.slice(separatorIndex + 1));
} }
} }
function parseEnvValue(rawValue: string): string { function parseEnvValue(rawValue: string): string {
const value = String(rawValue || '').trim() const value = String(rawValue || "").trim();
if (!value) { if (!value) {
return '' return "";
} }
const quote = value[0] const quote = value[0];
if ((quote === '"' || quote === "'") && value.endsWith(quote)) { if ((quote === '"' || quote === "'") && value.endsWith(quote)) {
return value.slice(1, -1) return value.slice(1, -1);
} }
return value return value;
} }
export function parseBoolean(rawValue: unknown): boolean | null { export function parseBoolean(rawValue: unknown): boolean | null {
const normalized = String(rawValue || '') const normalized = String(rawValue || "")
.trim() .trim()
.toLowerCase() .toLowerCase();
if (!normalized) { if (!normalized) {
return null return null;
} }
if (['1', 'true', 'yes', 'on'].includes(normalized)) { if (["1", "true", "yes", "on"].includes(normalized)) {
return true return true;
} }
if (['0', 'false', 'no', 'off'].includes(normalized)) { if (["0", "false", "no", "off"].includes(normalized)) {
return false return false;
} }
return null return null;
} }
export function parseInteger(rawValue: unknown): number | null { export function parseInteger(rawValue: unknown): number | null {
const normalized = String(rawValue || '').trim() const normalized = String(rawValue || "").trim();
if (!normalized) { if (!normalized) {
return null return null;
} }
const parsed = Number(normalized) const parsed = Number(normalized);
return Number.isFinite(parsed) ? parsed : null return Number.isFinite(parsed) ? parsed : null;
} }
export function parseJsonArray<T = unknown>(rawValue: unknown): T[] | null { export function parseJsonArray<T = unknown>(rawValue: unknown): T[] | null {
const normalized = String(rawValue || '').trim() const normalized = String(rawValue || "").trim();
if (!normalized) { if (!normalized) {
return null return null;
} }
try { try {
const parsed = JSON.parse(normalized) const parsed = JSON.parse(normalized);
return Array.isArray(parsed) ? parsed as T[] : null return Array.isArray(parsed) ? (parsed as T[]) : null;
} catch { } catch {
return null return null;
} }
} }
export function parseCommaSeparatedStrings(rawValue: unknown): string[] | null {
const normalized = String(rawValue || "").trim();
if (!normalized) {
return null;
}
const items = normalized
.split(",")
.map((item) => item.trim())
.filter((item) => item.length > 0);
return items.length > 0 ? items : null;
}