Repository navigation
Declare a boolean root schema (true/false) as unknown/never instead of emitting an empty file — lands after #884 - #887
Draft
claude[bot] wants to merge 5 commits into
Draft
claude[bot] wants to merge 5 commits into
claude[bot] wants to merge 5 commits into
Conversation
…leaking the `KeyNameFromDefinitionItems` placeholder
The array branch of the parser handed its items the literal key
`{keyNameFromDefinition}Items` (a template literal without `${}`), and a
titleless `enum` with `tsEnumNames` among the items took that as its
declared name. Items now get the array's name, else its property key,
plus `Items`; the copy of a nullable array (`type: ['array', 'null']`)
inherits the same. Where the array has neither, an `anyOf` branch say,
the enum degrades to a union of literals like any other unnamed enum.
Drops the filter that skipped the placeholder when naming anonymous
recursive types.
…s after the schema above An array that is a oneOf/anyOf branch, an allOf member, a tuple slot or additionalItems has no key of its own, so its items had none either and a titleless tsEnumNames enum among them fell back to a union of literals (under inferStringEnumKeysFromValues the Azure deployment template lost 265 enum declarations). Such an array now takes the key or name of the schema above it, so its items are named `<Key>Items` like a plain array's; a bare enum in those positions still stays a union of literals. Also drops the CHANGELOG hunk: the entry goes in the pull request body.
An array inside a oneOf within an anyOf, an anyOf within an allOf, or an OpenAPI `nullable: true` array that is itself a oneOf branch (the normalizer nests an anyOf inside that oneOf) sat two keyless levels down, so it still got no key and its titleless tsEnumNames enum fell back to a union of literals. A set operation in a keyless position now passes the key on to its members, unless it carries an enum of its own, which would otherwise be declared under the property's name.
…nstead of emitting an empty file A document that is nothing but `true` or `false` (a boolean schema, draft 6+) compiled to the banner comment alone, since the root had no keyword to be named by and so was never declared; with `unreachableDefinitions` on, or through `compileFiles`, it crashed. The root is now declared under the file's name, as an object root without an `$id` already is: `export type File = unknown;` for `true`, `= never;` for `false`. `compile()` accepts a boolean. The eight boolean_schema.json groups of the JSON-Schema-Test-Suite move from "invalid-output" to fully supported in the conformance baseline.
# Conflicts: # src/parser.ts
true/false) as unknown/never instead of emitting an empty filetrue/false) as unknown/never instead of emitting an empty file — lands after #884
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Draft until #884 lands — nothing for you to do. This branch carries #884's head merged in (one import line in src/parser.ts conflicted; both branches touch that file), so merging this before #884 would land #884's change with it.
Output change, for boolean root schemas only: a schema file that is nothing but
trueorfalsenow compiles to a named type instead of an empty file. Every other schema's output is byte-identical (checked below).What changes for you
From draft 6 on, a JSON Schema document may be a bare boolean:
trueaccepts every value,falseaccepts none. This compiler emitted nothing but the banner comment for such a file, because the root had no keyword to be named by and so was never declared. WithunreachableDefinitionson, or throughcompileFiles, it crashed (Cannot read properties of undefined (reading 'has')).Now the root is declared under the file's name, the same rule an object root without an
$idalready follows, andcompile()accepts a boolean:Anything.jsoncontainingtrueexport type Anything = unknown;Nothing.jsoncontainingfalseexport type Nothing = never;compile(true, 'Root')export type Root = unknown;compile(false, 'Root')export type Root = never;echo true | json2ts(stdin)export type NoName = unknown;compile(true, 'Root', {unreachableDefinitions: true}),compileFileswith a boolean memberThe library, the CLI (file, stdin, YAML, directory,
--imports),compileFromFileandcompileFilesall go through the same path.--no-unknownAnygivesany, as for every othertrueschema. ThecustomNameoption is not consulted for a boolean root, since that function is handed schema objects; the file name is the name.How
parseRoot(src/parser.ts): a boolean root getsparseBooleanSchema's node plus a standalone name; an object root goes toparseas before.parseUnreachableDefinitionsreturns nothing for a boolean root instead of reading its (absent) type set.rootNameFromFile(src/utils.ts): the one rule for a root without a name of its own (toSafeString(justName(file)) || 'NoName'), now shared by the normalizer's$idrule and the parser.compile()'sschemaparameter acceptsboolean. Nothing else in the public API changes.true/falseerrors (and no longer says a$refto one crashes, which Fix crash on $ref to a boolean schema or other non-object value (#725) #809 fixed).Tests
booleanSchemaRoot.true.tsandbooleanSchemaRoot.false.ts(two snapshot entries, placed besiderefToBooleanSchema.ts; no existing entry changes).compileFromFiletest withtest/resources/BooleanRoot/{Anything,Nothing}.json, asserting the full output including the banner; two CLI tests (file, stdin).5caacfcand pass here. Suite:CI=true bun run test687 pass / 0 fail atfef9931(master: 680 / 0); 691 / 0 at7ff419a(with Name an array's enum items after the array (RolesItems) instead of leaking theKeyNameFromDefinitionItemsplaceholder #884's four).bun run corpus: 26 schemas × 3 option sets compile and type-check; the 78 outputs (--e2e --out) are byte-identical to master's atfef9931, and at7ff419abyte-identical to Name an array's enum items after the array (RolesItems) instead of leaking theKeyNameFromDefinitionItemsplaceholder #884's own head's (the only differences from master are Name an array's enum items after the array (RolesItems) instead of leaking theKeyNameFromDefinitionItemsplaceholder #884's disclosed renames).Conformance baseline
bun run conformanceon master reports the eightboolean_schema.jsongroups (drafts 6, 7, 2019-09, 2020-12;trueandfalseeach) asinvalid-output(noRootdeclaration). They now score perfectly, sotest/conformance/baseline.jsonis re-recorded (node test/conformance/run.js --update): the eight group lines change from"invalid-output"to[0,9,0,0](true: 0 of 9 valid instances rejected) and[0,0,0,9](false: 0 of 9 invalid instances accepted), and the totals move accordingly (invalid-output8 → 0, valid instances 5262 → 5298, invalid instances 3606 → 3642). No other line moves; the harness exits 0 on this head.Merge check
git merge-tree --write-treeoffef9931against each open draft: clean against #879, #880, #881, #882, #883, #885, #886; conflicts with #884 on theimport … from './utils'line of src/parser.ts (#884 addshasType, this addsrootNameFromFile). Resolved by merging #884's head9488e4finto this branch (7ff419a, import line takes both names, nothing else hand-edited): snapshot interdiff against master is exactly this PR's two entries plus #884's own diff, suite and conformance green. So this lands after #884; once #884 is on master the merge commit is a no-op.Changelog
true/false) compiles toexport type X = unknown/neverinstead of an empty file (and no longer crashes withunreachableDefinitionsorcompileFiles).