From cb55b4a40d97be600fd053fee318bfb8971ace5f Mon Sep 17 00:00:00 2001 From: Altay Date: Fri, 22 May 2026 00:02:08 +0300 Subject: [PATCH] refactor(cli): tidy config schema path helpers --- src/cli/config-cli.test.ts | 51 +++++++++++++++++--------------------- src/cli/config-cli.ts | 27 ++++++++++++++++---- 2 files changed, 45 insertions(+), 33 deletions(-) diff --git a/src/cli/config-cli.test.ts b/src/cli/config-cli.test.ts index b9444db2ae2..41615ed76b8 100644 --- a/src/cli/config-cli.test.ts +++ b/src/cli/config-cli.test.ts @@ -181,6 +181,27 @@ function createPluginMetadataSnapshot( }; } +function configRecordWithRequireMentionSchema() { + return { + type: "object", + additionalProperties: { + type: "object", + properties: { + requireMention: { type: "boolean" }, + }, + }, + }; +} + +function configChannelSchemaWithRecord(recordKey: string) { + return { + type: "object", + properties: { + [recordKey]: configRecordWithRequireMentionSchema(), + }, + }; +} + function setConfigMutationShapeSchema() { mockReadBestEffortRuntimeConfigSchema.mockResolvedValue({ schema: { @@ -205,34 +226,8 @@ function setConfigMutationShapeSchema() { channels: { type: "object", properties: { - discord: { - type: "object", - properties: { - guilds: { - type: "object", - additionalProperties: { - type: "object", - properties: { - requireMention: { type: "boolean" }, - }, - }, - }, - }, - }, - telegram: { - type: "object", - properties: { - groups: { - type: "object", - additionalProperties: { - type: "object", - properties: { - requireMention: { type: "boolean" }, - }, - }, - }, - }, - }, + discord: configChannelSchemaWithRecord("guilds"), + telegram: configChannelSchemaWithRecord("groups"), }, }, }, diff --git a/src/cli/config-cli.ts b/src/cli/config-cli.ts index 6e80aa2927e..3fb668e4bc7 100644 --- a/src/cli/config-cli.ts +++ b/src/cli/config-cli.ts @@ -488,7 +488,14 @@ function schemaTypes(schema: JsonSchemaRecord): Set { return new Set(); } -function schemaAlternatives(schema: JsonSchemaRecord): JsonSchemaRecord[] { +function schemaAlternatives( + schema: JsonSchemaRecord, + seen = new Set(), +): JsonSchemaRecord[] { + if (seen.has(schema)) { + return []; + } + seen.add(schema); const alternatives: JsonSchemaRecord[] = [schema]; for (const key of ["anyOf", "oneOf", "allOf"] as const) { const entries = schema[key]; @@ -497,7 +504,7 @@ function schemaAlternatives(schema: JsonSchemaRecord): JsonSchemaRecord[] { } for (const entry of entries) { if (isSchemaRecord(entry)) { - alternatives.push(...schemaAlternatives(entry)); + alternatives.push(...schemaAlternatives(entry, seen)); } } } @@ -505,7 +512,11 @@ function schemaAlternatives(schema: JsonSchemaRecord): JsonSchemaRecord[] { } function schemaLooksArray(schema: JsonSchemaRecord): boolean { - return schemaTypes(schema).has("array") || isSchemaRecord(schema.items); + return ( + schemaTypes(schema).has("array") || + isSchemaRecord(schema.items) || + Array.isArray(schema.items) + ); } function schemaLooksObject(schema: JsonSchemaRecord): boolean { @@ -522,8 +533,14 @@ function propertySchema(schema: JsonSchemaRecord, segment: PathSegment): JsonSch const schemas: JsonSchemaRecord[] = []; for (const alternative of schemaAlternatives(schema)) { if (schemaLooksArray(alternative)) { - if (isIndexSegment(segment) && isSchemaRecord(alternative.items)) { - schemas.push(alternative.items); + if (isIndexSegment(segment)) { + const index = Number.parseInt(segment, 10); + const indexedItem = Array.isArray(alternative.items) + ? alternative.items[index] + : alternative.items; + if (isSchemaRecord(indexedItem)) { + schemas.push(indexedItem); + } } continue; }