fix(protocol): keep Swift array item types stable

This commit is contained in:
Peter Steinberger
2026-04-23 05:06:38 +01:00
parent 2c25e1d58d
commit 675cf823fd

View File

@@ -80,12 +80,54 @@ function safeName(name: string) {
// filled later once schemas are loaded
const schemaNameByObject = new Map<object, string>();
const schemaNameBySignature = new Map<string, string>();
const duplicateSchemaSignatures = new Set<string>();
function swiftType(schema: JsonSchema, required: boolean): string {
function stableJson(value: unknown): unknown {
if (Array.isArray(value)) {
return value.map(stableJson);
}
if (value && typeof value === "object") {
const record = value as Record<string, unknown>;
return Object.fromEntries(
Object.keys(record)
.toSorted()
.map((key) => [key, stableJson(record[key])]),
);
}
return value;
}
function schemaSignature(schema: JsonSchema): string {
return JSON.stringify(stableJson(schema));
}
function registerNamedSchema(name: string, schema: JsonSchema): void {
schemaNameByObject.set(schema as object, name);
const signature = schemaSignature(schema);
if (duplicateSchemaSignatures.has(signature)) {
return;
}
if (schemaNameBySignature.has(signature)) {
schemaNameBySignature.delete(signature);
duplicateSchemaSignatures.add(signature);
return;
}
schemaNameBySignature.set(signature, name);
}
function namedSchema(schema: JsonSchema, allowStructuralFallback = false): string | undefined {
return (
schemaNameByObject.get(schema as object) ??
(allowStructuralFallback ? schemaNameBySignature.get(schemaSignature(schema)) : undefined)
);
}
function swiftType(schema: JsonSchema, required: boolean, allowStructuralNamed = false): string {
const t = schema.type;
const isOptional = !required;
let base: string;
const named = schemaNameByObject.get(schema as object);
const named = namedSchema(schema, allowStructuralNamed);
if (named) {
base = named;
} else if (t === "string") {
@@ -97,7 +139,7 @@ function swiftType(schema: JsonSchema, required: boolean): string {
} else if (t === "boolean") {
base = "Bool";
} else if (t === "array") {
base = `[${swiftType(schema.items ?? { type: "Any" }, true)}]`;
base = `[${swiftType(schema.items ?? { type: "Any" }, true, true)}]`;
} else if (schema.enum) {
base = "String";
} else if (schema.patternProperties) {
@@ -214,7 +256,7 @@ async function generate() {
const definitions = Object.entries(ProtocolSchemas) as Array<[string, JsonSchema]>;
for (const [name, schema] of definitions) {
schemaNameByObject.set(schema as object, name);
registerNamedSchema(name, schema);
}
const parts: string[] = [];