Repository navigation
Conversation
…ties in 3.1 to 3.0
Effect 4 (via @orpc/effect) writes `additionalProperties: true` beside
`patternProperties` for records with number or template-literal keys and
for StructWithRest. Dropping it left a bare `{ type: object }`, which
openapi-typescript types as `Record<string, never>`. `true` allows every
property, so it never contradicts `patternProperties`; only schemas and
`false` are dropped now.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FZoWKNpDyGBHkdaur4kKtA
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes — read the full diff and verified the new assertion is live: reverting the && item !== true guard makes the changed test fail, and it passes with the fix.
additionalProperties: truepreserved besidepatternProperties(packages/downgrader/src/v3.1-to-v3.0.ts:148): the guard now drops only afalseor schema value, keeping the booleantrue, which allows every property and so never rejects what the removedpatternPropertiesallowed. A bare{ type: "object" }no longer leaks through asRecord<string, never>.- README row updated (
packages/downgrader/README.md:193): thepatternPropertiesrow now states that a schema (orfalse) is dropped butadditionalProperties: truestays. - Test extended (
packages/downgrader/tests/v3.1-to-v3.0.test.ts:1103): the existing case now also covers thefalse-beside-patternProperties drop, a schema value ({ type: "number" }→{}), and the kepttrue.
The change stays safe under the surrounding logic: patternProperties remains in RESTRICTING_KEYWORDS, so the output is still marked loose; isUnevaluatedAdditional stays false while patternProperties is present; and an existing additionalProperties keeps losesRestriction false for unevaluatedProperties, so nothing is mis-folded. 3.0 admits boolean additionalProperties, and true can only loosen relative to the removed keyword, matching the "loses detail, never meaning" contract.
deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏
… true in 3.0
The previous commit only kept an existing `additionalProperties: true`.
Every other object with `patternProperties` still came out of 3.0 as a
bare `{ type: object }`, which openapi-typescript types as
`Record<string, never>`: Zod `z.looseRecord` (no `additionalProperties`),
Effect records with `onExcessProperty: "error"` (`false`), an
`additionalProperties` schema, and `properties` beside `patternProperties`.
`finishSchema` now sets `additionalProperties: true` whenever
`patternProperties` is present, and the field converter drops the input
one as on main.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FZoWKNpDyGBHkdaur4kKtA
There was a problem hiding this comment.
ℹ️ The code change is sound — it can only loosen — but the README now under-describes it and a Limitations bullet contradicts the new behavior. One minor wording fix suggested inline.
Reviewed changes — re-reviewed the delta since the prior Pullfrog review (518de8b), which had kept additionalProperties: true in the field converter.
- Fix moved into
finishSchema(packages/downgrader/src/v3.1-to-v3.0.ts:654): the field converter is back to main's behavior (always drops the inputadditionalPropertiesbesidepatternProperties), andfinishSchemanow setsadditionalProperties: truewheneverschema.patternProperties !== undefined— soundefined,true,false, and schema inputs all end up astrue. - README row reworded (
packages/downgrader/README.md:193): thepatternPropertiesrow now says the additionalProperties becomestrue. - Test rewritten (
packages/downgrader/tests/v3.1-to-v3.0.test.ts:1103-1114): loops the fouradditionalPropertiesinputs and adds aproperties-beside-patternPropertiescase.
I confirmed the assertion is live (removing the finishSchema block fails the test with expected { type: 'object' } to deeply equal { type: 'object', additionalProperties: true }) and the full 90-test file passes. The change is safe by construction: dropping patternProperties and adding additionalProperties: true only widens acceptance, and patternProperties stays in RESTRICTING_KEYWORDS so the schema is still marked loose.
deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏
…ties: true Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FZoWKNpDyGBHkdaur4kKtA

Requested by dinwwwh · project thread
3.0 has no
patternProperties, so the 3.1 to 3.0 converter removes it, along with anyadditionalPropertiesbeside it (a schema orfalsethere would reject the propertiespatternPropertiesallowed). What's left is often a bare{ type: "object" }, and openapi-typescript types that asRecord<string, never>. Code generators read a missingadditionalPropertiesas "no other properties allowed".This shows up in real output:
z.looseRecord(patternProperties, noadditionalProperties)@orpc/effect:Schema.Record(Schema.Number, V), template-literal key records andStructWithRest(additionalProperties: true), and records withonExcessProperty: "error"(additionalProperties: false)patternPropertiesbeside anadditionalPropertiesschema, or besidepropertiescontacts/search/emailsresponseNow
finishSchemasetsadditionalProperties: truewheneverpatternPropertiesis present. The meaning doesn't change: a missingadditionalPropertiesalready allowed every property, and the schema is still marked as having lost a restriction.src/v3.1-to-v3.0.ts: theadditionalProperties = truestep infinishSchema. The field converter still drops the inputadditionalProperties, as on main.README.md: thepatternPropertiesrow saysadditionalPropertiesbecomestrue.tests/v3.1-to-v3.0.test.ts: the existing test checksadditionalPropertiesset to undefined,true,falseand a schema, plus a case withproperties. It fails without the fix.Checks: 262 tests pass and
pnpm run checkis clean.Note: #100's test expects
{ propertyNames: { enum }, patternProperties }to give{}. With this change it gives{ additionalProperties: true }, so whichever PR merges second needs that expectation updated.🤖 Generated with Claude Code
https://claude.ai/code/session_01FZoWKNpDyGBHkdaur4kKtA