[Snow Team] Merge config-fixer's work with conflict resolution
This commit is contained in:
@@ -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 {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user