Repository navigation
Conversation
…e in 3.1 to 3.0 Zod and Valibot write a record with enum keys as a propertyNames enum beside additionalProperties. 3.0 has no propertyNames, so generators typed it as a string-keyed map and an enclosing oneOf became anyOf. Each name now becomes a property sharing the additionalProperties schema, with additionalProperties: false. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VvmRkSSBRTofwpppUksACY
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
…moved Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VvmRkSSBRTofwpppUksACY
There was a problem hiding this comment.
ℹ️ No critical issues — minor suggestions inline.
Reviewed changes
propertyNamesenum → one property per name —enumNamesdetects the Zod/Valibot record shape andfinishSchemarewrites it intoproperties+additionalProperties: false;losesRestrictiontreats it as exact so an enclosingoneOfstays.- Test — covers the Zod shape, the bare shape, the removal cases, and the enclosing
oneOf. - README — new 3.1→3.0 table row for the enum case.
I checked semantic equivalence with an Ajv 2020-12 differential (49 applicable schema combos × 56 instances): input and converted output agreed everywhere except __proto__ enum names, which is an Ajv quirk (reproducible with a hand-written properties: { "__proto__": {} } schema) rather than a converter defect. pnpm test passes (263) and uncheck is clean on the touched files.
deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏
There was a problem hiding this comment.
ℹ️ No critical issues — one minor documentation suggestion inline.
Reviewed changes
Since the prior review (dbb858f), cea5a3e adds assertions to the propertyNames enum test pinning the cases where the conversion does not apply: additionalProperties: false, patternProperties, and a propertyNames carrying an extra keyword (minLength, type: "number"), plus an enum beside description: undefined. No production code changed.
propertyNamesenum → one property per name —enumNamesdetects the Zod/Valibot record shape andfinishSchemarewrites it intoproperties+additionalProperties: false;losesRestrictiontreats it as exact so an enclosingoneOfstays.- Tests — the Zod shape, the bare shape, the exact-conversion cases, the removal cases (now including
additionalProperties: falseandpatternProperties), and the enclosingoneOf. - README — new 3.1→3.0 table row.
I re-ran the mutation check on the additionalProperties === false guard: with the new test in place, removing that guard now fails the suite (previously all 263 passed), so the guard is genuinely covered. pnpm test is green and uncheck is clean on the touched files.
deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏
|
Follow-up to my review (the inline anchor did not attach): the new README row lists
|
|
Re the README row: I'm leaving it as is. With Generated by Claude Code |
Zod's .meta({ id }) enum keys and Pydantic dict[Enum, V] write a record's
keys as a $ref to a reusable enum. It is followed when nothing sits beside
it, so the record still gets one property per name.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VvmRkSSBRTofwpppUksACY
There was a problem hiding this comment.
ℹ️ No critical issues — one minor documentation note inline.
Reviewed changes
Since the prior review (cea5a3e), a8c9208 extends the propertyNames enum conversion to follow a $ref.
$ref-keyedpropertyNames—enumNamesnow resolves a$refthat stands alone inpropertyNamesto its target and reads theenumfrom there, andctxthreads throughlosesRestriction/loosenso the looseness check sees the same resolved names the rewrite does.- Tests — a new case covers a
$refto a reusable enum incomponents/$defs, the enclosingoneOfstaying aoneOf, and the removals for a non-enum target and a$refcarrying a sibling keyword. - README — the 3.1→3.0 table row now names the
$refform.
pnpm test (264) and pnpm run check (sherif/oxlint/oxfmt/tsc) are green on this commit.
deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏

Requested by dinwwwh · project thread
Zod
z.record(z.enum(['a', 'b']), V)andz.partialRecord, and Valibotv.record(v.picklist([...]), V), come out of oRPC as:{ "type": "object", "propertyNames": { "type": "string", "enum": ["a", "b"] }, "additionalProperties": V }(Zod adds
required.) A record keyed by a reusable enum (Zod.meta({ id }), Pydanticdict[Enum, V]) writespropertyNames: { "$ref": "#/components/schemas/Lang" }instead. 3.0 has nopropertyNames, so it was removed, generators typed the record asRecord<string, V>, and an enclosingoneOfbecameanyOfbecause the branch got looser.In 3.1 to 3.0, such a
propertyNamesnow becomes one property per name, each sharing the convertedadditionalPropertiesschema, plusadditionalProperties: false. That is exact, so an enclosingoneOfstays.It applies only when
propertyNamesholds just anenum(and optionallytype: "string"), or just a$refto such an enum, with noproperties,patternProperties,unevaluatedPropertiesoradditionalProperties: falsebeside it. Anything else keeps the current behavior (removed). A$refwith keywords beside it (such asmaxLength) is not followed, since those narrow the names further.Changes:
enumNameshelper and a matching line inlosesRestrictioninsrc/v3.1-to-v3.0.ts, plus six lines infinishSchema.ctxnow passes throughloosenandlosesRestrictionsoenumNamescan follow a$refwith the existingresolve.$refshape, the cases where it is still removed, and the enclosingoneOf.Checked:
pnpm test(264 pass) andpnpm run checkclean. Ajv agrees with the 3.1 input on the converted output for the enum-key record variants; 700 fuzzed oRPC Zod/Valibot docs stay valid 3.0 with no lost instances; 76 of 80 real docs are byte-identical to main's output.🤖 Generated with Claude Code
https://claude.ai/code/session_01VvmRkSSBRTofwpppUksACY