feat: support custom server deployment drafts

This commit is contained in:
npc0-hue
2026-07-24 16:56:28 +08:00
parent 292b380f3c
commit 220ef91a8e
36 changed files with 1520 additions and 85 deletions
+20
View File
@@ -111,6 +111,25 @@ function scanUnsafeValues(value: unknown, location: string): string[] {
return [];
}
function validateCreateFieldDeclarations(manifest: unknown): string[] {
if (typeof manifest !== "object" || manifest === null || !("server" in manifest)) return [];
const server = (manifest as { server?: { createFields?: Array<{ key?: unknown; type?: unknown; defaultValue?: unknown; options?: unknown }> } }).server;
if (!Array.isArray(server?.createFields)) return [];
const errors: string[] = [];
for (const [index, field] of server.createFields.entries()) {
const location = `manifest.server.createFields[${index}]`;
for (const [name, value] of [["defaultValue", field.defaultValue], ["options", field.options]] as const) {
const values = Array.isArray(value) ? value : [value];
for (const item of values) {
if (typeof item !== "string") continue;
if (item.startsWith("/") || item.startsWith("\\\\") || /^[a-z]:[\\/]/i.test(item)) errors.push(`${location}.${name}: raw host path access is not allowed`);
errors.push(...unsafeStringReasons(item).map((reason) => `${location}.${name}: ${reason}`));
}
}
}
return errors;
}
function isSafeRelativeJsonRef(value: string): boolean {
return /^(?!\/)(?![A-Za-z]:)(?!.*:\/\/)(?!.*\.\.)[a-zA-Z0-9_./-]+\.json$/.test(value);
}
@@ -1103,6 +1122,7 @@ export function validateManifestFile(manifestPath: string): string[] {
}
errors.push(...scanUnsafeValues(manifest, "manifest"));
errors.push(...validateCreateFieldDeclarations(manifest));
errors.push(...validateDependencyPlans(manifest));
errors.push(...validateClientManagerProfiles(manifest));
errors.push(...validateDLLExtensionProfiles(manifest));