refactor: 收敛 Sub2API parser label 拼接

This commit is contained in:
Codex
2026-06-14 05:38:08 +00:00
parent c5431420b8
commit a49395fcdc
+12 -9
View File
@@ -7,7 +7,7 @@ import { startJob } from "./jobs";
import type { RenderedCliResult } from "./output";
import { pk01CaddyMergeManagedBlocksPython, renderCaddyManagedBlock, renderSimpleReverseProxyCaddySiteBlock } from "./pk01-caddy";
import { capture, compactCapture, parseJsonOutput, prepareFrpcSecret, shQuote } from "./platform-infra-public-service";
import { yamlBooleanField, yamlIntegerField, yamlSubFieldLabel } from "./platform-infra-ops-library";
import { yamlBooleanField, yamlFieldLabel, yamlIntegerField } from "./platform-infra-ops-library";
import { fingerprintSecretValues, parseEnvFile, readEnvSourceFile, readTextFile, redactRepoPath, requiredEnvValue } from "./secrets";
const serviceName = "sub2api";
@@ -773,47 +773,50 @@ function parseRuntime(root: Record<string, unknown>): Sub2ApiConfig["runtime"] {
function stringField(obj: Record<string, unknown>, key: string, path: string): string {
const value = obj[key];
if (typeof value !== "string" || value.length === 0) throw new Error(`${configPath}.${path}.${key} must be a non-empty string`);
if (typeof value !== "string" || value.length === 0) throw new Error(`${fieldLabel(path, key)} must be a non-empty string`);
return value;
}
function objectField(obj: Record<string, unknown>, key: string, path: string): Record<string, unknown> {
const value = obj[key];
const prefix = path.length > 0 ? `${path}.` : "";
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error(`${configPath}.${prefix}${key} must be an object`);
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error(`${fieldLabel(path, key)} must be an object`);
return value as Record<string, unknown>;
}
function booleanField(obj: Record<string, unknown>, key: string, path: string): boolean {
return yamlBooleanField(obj, key, yamlSubFieldLabel(configPath, path), "");
return yamlBooleanField(obj, key, configPath, path);
}
function stringArrayField(obj: Record<string, unknown>, key: string, path: string): string[] {
const value = obj[key];
if (!Array.isArray(value) || !value.every((item) => typeof item === "string" && item.trim().length > 0)) {
throw new Error(`${configPath}.${path}.${key} must be an array of non-empty strings`);
throw new Error(`${fieldLabel(path, key)} must be an array of non-empty strings`);
}
return value.map((item) => item.trim());
}
function enumField<const T extends readonly string[]>(obj: Record<string, unknown>, key: string, path: string, values: T): T[number] {
const value = stringField(obj, key, path);
if (!(values as readonly string[]).includes(value)) throw new Error(`${configPath}.${path}.${key} must be one of ${values.join(", ")}`);
if (!(values as readonly string[]).includes(value)) throw new Error(`${fieldLabel(path, key)} must be one of ${values.join(", ")}`);
return value as T[number];
}
function integerField(obj: Record<string, unknown>, key: string, path: string): number {
return yamlIntegerField(obj, key, yamlSubFieldLabel(configPath, path), "");
return yamlIntegerField(obj, key, configPath, path);
}
function integerArrayField(obj: Record<string, unknown>, key: string, path: string): number[] {
const value = obj[key];
if (!Array.isArray(value) || !value.every((item) => typeof item === "number" && Number.isInteger(item))) {
throw new Error(`${configPath}.${path}.${key} must be an array of integers`);
throw new Error(`${fieldLabel(path, key)} must be an array of integers`);
}
return value;
}
function fieldLabel(path: string, key: string): string {
return yamlFieldLabel(configPath, path, key);
}
function isKubernetesName(value: string): boolean {
return /^[a-z0-9]([-a-z0-9]*[a-z0-9])?$/u.test(value);
}