docs: update union member resolution documentation

Refactor union resolution to explicitly try reference members before
non-reference members. This replaces the previous error-message-based
fallback with a deterministic, structural approach.

- Update `parseValueWithReferences` and `resolveNestedReferences` to
  partition members by reference presence.
- Update documentation in `README.md`, `AGENTS.md`, and
  `syntax-rework-plan.md` to reflect this behavior.
This commit is contained in:
2026-08-06 09:32:10 +08:00
parent c969c7f6fc
commit cdff31c126
4 changed files with 44 additions and 54 deletions
+33 -44
View File
@@ -299,39 +299,27 @@ export function parseValueWithReferences(
);
}
case "union": {
// Try reference members first (more specific), then non-reference members.
// This makes the fallback structural rather than error-message-driven.
const refMembers = schema.members.filter(hasNestedReferences);
const nonRefMembers = schema.members.filter((m) => !hasNestedReferences(m));
const errors: Error[] = [];
for (const member of schema.members) {
if (hasNestedReferences(member)) {
try {
const parsed = parseValue(member, valueString);
return resolveNestedReferences(
parsed,
member,
refBaseDir,
defaultPrimaryKey,
currentFilePath,
currentRowPk,
);
} catch (e) {
errors.push(e instanceof Error ? e : new Error(String(e)));
}
for (const member of [...refMembers, ...nonRefMembers]) {
try {
const parsed = parseValue(member, valueString);
return resolveNestedReferences(
parsed,
member,
refBaseDir,
defaultPrimaryKey,
currentFilePath,
currentRowPk,
);
} catch (e) {
errors.push(e instanceof Error ? e : new Error(String(e)));
}
}
if (
errors.length > 0 &&
errors.every((e) =>
/not found|Circular reference|Failed to load/.test(e.message),
)
) {
for (const member of schema.members) {
if (!hasNestedReferences(member)) {
try {
return parseValue(member, valueString);
} catch {}
}
}
}
return parseValue(schema, valueString);
throw errors[0] ?? new Error("Value does not match any union member");
}
default:
return parseValue(schema, valueString);
@@ -425,21 +413,22 @@ export function resolveNestedReferences(
);
}
case "union": {
// Try reference members first (more specific), then non-reference members.
const refMembers = schema.members.filter(hasNestedReferences);
const nonRefMembers = schema.members.filter((m) => !hasNestedReferences(m));
const errors: Error[] = [];
for (const member of schema.members) {
if (hasNestedReferences(member)) {
try {
return resolveNestedReferences(
value,
member,
refBaseDir,
defaultPrimaryKey,
currentFilePath,
currentRowPk,
);
} catch (e) {
errors.push(e instanceof Error ? e : new Error(String(e)));
}
for (const member of [...refMembers, ...nonRefMembers]) {
try {
return resolveNestedReferences(
value,
member,
refBaseDir,
defaultPrimaryKey,
currentFilePath,
currentRowPk,
);
} catch (e) {
errors.push(e instanceof Error ? e : new Error(String(e)));
}
}
if (errors.length > 0) {