feat: align frontend runtime and Edge TTS

This commit is contained in:
2026-07-22 15:01:25 +08:00
parent d2c278f0ea
commit 699a0bced4
43 changed files with 2000 additions and 73 deletions
+8
View File
@@ -33,4 +33,12 @@ describe("runtime frontend configuration", () => {
it("rejects invalid runtime URLs before the application starts", () => {
expect(() => parseRuntimeConfig({ TJWATER_MAP_URL: "not-a-url" })).toThrow();
});
it.each([
["TJWATER_MAP_URL", "file:///etc/passwd"],
["TJWATER_AGENT_API_BASE_URL", "https://user:secret@agent.example.test"],
["TJWATER_AGENT_API_BASE_URL", "https://agent.example.test/#secret"]
])("rejects unsafe browser runtime address %s", (key, value) => {
expect(() => parseRuntimeConfig({ [key]: value })).toThrow();
});
});
+19 -3
View File
@@ -6,11 +6,27 @@ const runtimeBoolean = (defaultValue: boolean) =>
.default(defaultValue ? "true" : "false")
.transform((value) => value === "true");
const browserHttpUrl = z
.string()
.url()
.superRefine((value, context) => {
const url = new URL(value);
if (!["http:", "https:"].includes(url.protocol)) {
context.addIssue({ code: z.ZodIssueCode.custom, message: "仅支持 HTTP(S) 地址" });
}
if (url.username || url.password) {
context.addIssue({ code: z.ZodIssueCode.custom, message: "浏览器运行时地址不能包含凭据" });
}
if (url.hash) {
context.addIssue({ code: z.ZodIssueCode.custom, message: "浏览器运行时地址不能包含片段" });
}
});
const runtimeConfigSchema = z.object({
TJWATER_MAPBOX_ACCESS_TOKEN: z.string().default(""),
TJWATER_MAP_URL: z.string().url().default("https://geoserver.waternetwork.cn/geoserver"),
TJWATER_GEOSERVER_WORKSPACE: z.string().min(1).default("tjwater"),
TJWATER_AGENT_API_BASE_URL: z.string().url().default("http://127.0.0.1:8787"),
TJWATER_MAP_URL: browserHttpUrl.default("https://geoserver.waternetwork.cn/geoserver"),
TJWATER_GEOSERVER_WORKSPACE: z.string().trim().min(1).default("tjwater"),
TJWATER_AGENT_API_BASE_URL: browserHttpUrl.default("http://127.0.0.1:8787"),
TJWATER_ENABLE_DEV_PANEL: runtimeBoolean(false),
TJWATER_ENABLE_MSW: runtimeBoolean(false)
});