Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
104 commits
Select commit Hold shift + click to select a range
931c6af
improve typings for TS with array
tolbon May 13, 2023
49ea0d9
Merge branch 'master' into feat/min_max_array
dvdsgl May 16, 2023
a60d0b2
rm some error
tolbon May 17, 2023
3820de4
fix add typo ArrayT in TypesScriptFlow
tolbon May 21, 2023
01ba686
Merge branch 'master' into feat/min_max_array
dvdsgl Jun 4, 2023
d794381
feat(Rust): Add integer type inference option
jonashao Jun 23, 2025
af0c9ff
feat: Add support for unevaluatedProperties in JSON Schema
haya14busa Jul 5, 2025
ccb783f
Merge master and resolve conflicts
schani Jul 9, 2026
8493ff4
feat(kotlin)!: default framework is now jackson
schani Jul 19, 2026
fa3eb91
feat(csharp)!: default framework is now SystemTextJson
schani Jul 19, 2026
e2d5790
feat(cplusplus)!: boost is now off by default
schani Jul 19, 2026
4e65b12
feat(rust)!: public fields and Debug/Clone derives by default; remove…
schani Jul 19, 2026
130bd6f
feat(typescript)!: prefer-unions is now on by default
schani Jul 19, 2026
dd01522
feat(java)!: arrays now render as List<T> by default
schani Jul 19, 2026
06f7556
feat(dart)!: final properties by default; remove null-safety option
schani Jul 19, 2026
120c958
feat(swift)!: density now defaults to normal; remove swift-5-support
schani Jul 19, 2026
dd91f6f
feat(haskell)!: arrays now render as lists by default
schani Jul 19, 2026
3b2cb1b
fix(cplusplus): preserve JSON null in std::optional/shared_ptr deseri…
schani Jul 20, 2026
e78765a
fix(java): carry element types in union list deserialization
schani Jul 20, 2026
370d904
Merge remote-tracking branch 'origin/master' into major-default-flips
schani Jul 20, 2026
02da1cd
build(deps): bump stream-json from 1.8.0 to 3.5.0
dependabot[bot] Jul 20, 2026
6285309
feat(csharp)!: default csharp-version is now 8
schani Jul 20, 2026
643fef6
fix: migrate to stream-json 3.x API
schani Jul 20, 2026
4800181
fix(elm): generate Elm 0.19 code
schani Jul 20, 2026
e7b277b
feat(elm): default array-type to list
schani Jul 20, 2026
cba6330
test(elm): revive Elm fixtures on Elm 0.19 and re-enable them in CI
schani Jul 20, 2026
0926136
fix(csharp): never double the nullable annotation on optional union p…
schani Jul 20, 2026
f9c4521
test(elm): move the Elm toolchain to 0.19.2
schani Jul 20, 2026
1b96c26
Merge pull request #2959 from glideapps/elm-0.19
schani Jul 20, 2026
f258d88
Merge pull request #2954 from glideapps/dependabot/npm_and_yarn/strea…
schani Jul 20, 2026
08a1501
Merge master (Elm 0.19, ajv 8, stream-json 3)
schani Jul 20, 2026
e143288
Merge pull request #2960 from glideapps/elm-0.19
schani Jul 20, 2026
5990c74
Raise engines.node to >=20.19.0
schani Jul 20, 2026
eacbf4e
Merge pull request #2952 from glideapps/major-default-flips
schani Jul 20, 2026
0893d55
Merge remote-tracking branch 'origin/master' into HEAD
schani Jul 20, 2026
27c1f84
Fix biome formatting in JSONSchemaInput.ts
schani Jul 20, 2026
61f95a0
test(schema): prove unevaluatedProperties values are typed, not any
schani Jul 20, 2026
57dd956
Merge origin/master into rust-integer-type-fixes-2791
schani Jul 20, 2026
1ddaf28
fix(rust): require both bounds for conservative i32 inference
schani Jul 20, 2026
858ddde
Merge origin/master into PR #2272
schani Jul 20, 2026
b47f541
Drop the dead minContains/maxContains attribute kind
schani Jul 20, 2026
e92c26a
Read minItems/maxItems off the array type; tuples only in TypeScript
schani Jul 20, 2026
cc4567a
test: fixture-test the Rust integer-type option end to end
schani Jul 20, 2026
a63c6fd
Let arrays carry identity attributes through graph rewriting
schani Jul 20, 2026
615b20b
test: expected-output fixtures for JSON inputs
schani Jul 20, 2026
b66dd02
feat(csharp): option to suppress DateOnly/TimeOnly converters (System…
schani Jul 20, 2026
6c5b447
Add min-max-items fixture tests
schani Jul 20, 2026
8f09c21
Skip pre-existing schema-typescript failures
schani Jul 20, 2026
3de9cc2
Merge pull request #2961 from glideapps/json-expected-output-fixtures
schani Jul 20, 2026
6d81f82
Merge pull request #2962 from glideapps/csharp-dateonly-optout
schani Jul 20, 2026
cef6206
test(elm): retry elm make after clearing elm-stuff
schani Jul 20, 2026
044ed8d
Merge pull request #2800 from haya14busa/fix-unevaluated-properties-s…
schani Jul 20, 2026
0591fdb
Merge pull request #2963 from glideapps/elm-make-retry
schani Jul 20, 2026
b30d262
Merge branch 'master' into rust-integer-type-fixes-2791
schani Jul 20, 2026
b632d03
Fix process.process.exit typo in the test harness error path
schani Jul 20, 2026
2b26cc7
Merge pull request #2964 from glideapps/rust-integer-type-fixes-2791
schani Jul 20, 2026
b204a47
Merge pull request #2965 from glideapps/fix-test-harness-exit-typo
schani Jul 20, 2026
d45a3fe
Merge branch 'master' into feat/min_max_array
schani Jul 20, 2026
e52e675
Skip min-max-items.schema for kotlinx
schani Jul 20, 2026
bbd38a7
Merge commit 'refs/prtriage/2272-now' into HEAD
schani Jul 20, 2026
408d4ff
Merge pull request #2272 from tolbon/feat/min_max_array
schani Jul 20, 2026
56737ce
fix(typescript-zod): preserve null for nullable date-time fields (#2880)
schani Jul 20, 2026
d12b24f
fix(schema-input): report clean fetch error for missing schema paths …
schani Jul 20, 2026
1885cad
fix(typescript-input): strip brace-wrapped types from JSDoc @type tag…
schani Jul 20, 2026
45e6700
fix(json-schema): recognize $defs when deriving type names (#2778)
schani Jul 20, 2026
544ed4b
fix(dart): preserve null for optional list properties (#2656)
schani Jul 20, 2026
24db806
fix(cli): surface clear error for duplicate -o instead of internal er…
schani Jul 20, 2026
44fe04b
fix(schema): emit min/max constraints for applicable type kinds (#2557)
schani Jul 20, 2026
e52d530
fix(csharp): throw JsonException/NotSupportedException in SystemTextJ…
schani Jul 20, 2026
4b6e2b3
fix(typescript): annotate m() helper's props array to satisfy noImpli…
schani Jul 20, 2026
15599a4
fix(c++): include Generators.hpp and name real types in multi-source …
schani Jul 20, 2026
ddab493
fix(cpp): support std::optional in Utf16_Utf8 string conversion (#2383)
schani Jul 20, 2026
aa83b1c
fix(cpp): silence unused-parameter warnings for empty objects (#2362)
schani Jul 20, 2026
806a112
fix(csharp): always emit <auto-generated /> header (#1973)
schani Jul 20, 2026
29924ab
Merge pull request #2986 from glideapps/agent/fix-issue-1973
schani Jul 20, 2026
35f131a
Merge pull request #2981 from glideapps/agent/fix-issue-2383
schani Jul 20, 2026
315d986
fix(dart): keep top-level fromJson/toJson names with --from-map (#1719)
schani Jul 20, 2026
3b97769
fix(input): reject non-OK HTTP responses when reading from a URL (#2572)
schani Jul 20, 2026
d235426
Merge pull request #3014 from glideapps/agent/fix-issue-2572
schani Jul 20, 2026
47f5a83
Merge pull request #2966 from glideapps/agent/fix-issue-2880
schani Jul 20, 2026
f77b9b9
Merge pull request #2967 from glideapps/agent/fix-issue-2812
schani Jul 20, 2026
7e694d9
Merge pull request #2972 from glideapps/agent/fix-issue-2457
schani Jul 20, 2026
f58485e
fix(core): preserve JSON Schema enum case order (#1289)
schani Jul 20, 2026
92811f5
Merge pull request #2970 from glideapps/agent/fix-issue-2778
schani Jul 20, 2026
0dee142
Merge pull request #2971 from glideapps/agent/fix-issue-2656
schani Jul 20, 2026
1886c1c
Merge pull request #2976 from glideapps/agent/fix-issue-2364
schani Jul 20, 2026
978a423
Merge pull request #3000 from glideapps/agent/fix-issue-1719
schani Jul 20, 2026
fb1af69
docs: require positive and negative cases for schema fixture tests
schani Jul 20, 2026
89d9f2a
fix(cjson): start enum values at 1 so invalid/missing input is distin…
schani Jul 20, 2026
1ab2a02
fix(schema): keep allOf-merged properties when a branch sets addition…
schani Jul 20, 2026
fd68cc8
Merge pull request #3028 from glideapps/agent/fix-issue-1289
schani Jul 20, 2026
d545d83
fix(python): try integer before number in union deserialization (#1318)
schani Jul 20, 2026
e977e88
docs: document known CI flakiness and retry policy
schani Jul 20, 2026
349bc78
test(cjson): skip enum-value fail sample for all-of merge schema
schani Jul 21, 2026
4fa7cc1
test(cjson): skip schema-constraints.schema
schani Jul 21, 2026
b2d88d3
docs: prefer fixture tests over unit tests when both can cover a change
schani Jul 21, 2026
bbc3134
Merge pull request #3058 from glideapps/agent/fix-issue-1257
schani Jul 21, 2026
55ec1d1
Merge pull request #2975 from glideapps/agent/fix-issue-2557
schani Jul 21, 2026
3003456
Merge pull request #2968 from glideapps/agent/fix-issue-2695
schani Jul 21, 2026
cbd196d
Merge pull request #2977 from glideapps/agent/fix-issue-2430
schani Jul 21, 2026
24b5c45
Merge pull request #2982 from glideapps/agent/fix-issue-2362
schani Jul 21, 2026
d29168a
Merge pull request #2978 from glideapps/agent/fix-issue-2438
schani Jul 21, 2026
6664275
Merge pull request #3052 from glideapps/agent/fix-issue-2357-run2
schani Jul 21, 2026
fa893ca
Merge pull request #3059 from glideapps/agent/fix-issue-1318-b
schani Jul 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions .github/workflows/test-pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,12 @@
- scala3,schema-scala3
- scala3-upickle,schema-scala3-upickle
- elixir,schema-elixir,graphql-elixir
- elm,schema-elm
- comment-injection-treesitter,comment-injection-typescript,comment-injection-typescript-zod,comment-injection-typescript-effect-schema

# Partially working
# - schema-typescript # TODO Unify with typescript once fixed

# Implementation is too outdated to test in GitHub Actions
# - elm,schema-elm

# Language is too niche / obscure to test easily on ubuntu-22.04
# - pike,schema-pike

Expand Down Expand Up @@ -136,7 +134,7 @@
- name: Install Elm
if: ${{ contains(matrix.fixture, 'elm') }}
run: |
curl -L -o elm.gz https://github.com/elm/compiler/releases/download/0.19.1/binary-for-linux-64-bit.gz
curl -L -o elm.gz https://github.com/elm/compiler/releases/download/0.19.2/elm-0.19.2-linux-x64.gz

Check warning on line 137 in .github/workflows/test-pr.yaml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Not enforcing HTTPS here might allow for redirections to insecure websites. Make sure it is safe here.

See more on https://sonarcloud.io/project/issues?id=meonBot_quicktype&issues=AZ-A5YAZ_NIpiBVoTVEA&open=AZ-A5YAZ_NIpiBVoTVEA&pullRequest=72
gunzip elm.gz
chmod +x elm
sudo mv elm /usr/local/bin/
Expand Down
27 changes: 26 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ JSON to the input.
`.N.json` samples and `.N.fail.<feature>.json` expected-failure samples. A
fail sample must make the generated program exit nonzero; which fail
samples run is controlled by the language's `features` list.
- Every schema fixture test must have at least one positive (`.N.json`) and
one negative (`.N.fail.<feature>.json`) test case, unless there is a very
good reason not to.
- Per-language configuration — which inputs run (`skipJSON`, `includeJSON`,
`skipSchema`), renderer options, and `features` — lives in
`test/languages.ts`; fixtures are registered in `test/fixtures.ts`.
Expand All @@ -25,7 +28,29 @@ Any change that affects generated output MUST be covered by a JSON or JSON
Schema fixture test — by enabling existing inputs for the language or adding
new ones. Unit tests in `test/unit/` are a complement for what fixtures cannot
express (asserting that some code is *not* generated, API-level behavior, fast
local iteration) — never a substitute.
local iteration) — never a substitute. Do not add a unit test when a fixture
test will do the job: if a fixture input already exercises the behavior, a
unit test duplicating that coverage is superfluous and should not be added.

## Known CI flakiness

Three fixture-CI failure modes are infrastructure flakes, not test or PR bugs:

- **scala3-upickle**: the Bloop compiler server sometimes times out after 30
seconds at startup, and `maven-nightlies` artifact downloads sometimes fail.
- **elm**: the fixture setup (`rm -rf elm-stuff && elm make Warmup.elm`) can
race the compiler, deadlocking on `elm-stuff/*.dat` file locks.
- **cjson**: `cJSON.c` is downloaded from raw.githubusercontent.com at test
time and can hit transient SSL/connection failures.

Two things amplify them: the fixture matrix runs with `fail-fast: true`, so
one flaky job cancels all sibling language jobs, and the `test-complete`
check only mirrors the matrix — it is never an independent failure.

For the time being we accept these flakes; when one happens, retry the failed
jobs (`gh run rerun <run-id> --failed`). A failure in one of these areas only
counts as real if it reproduces across retries or the PR actually touches
that area.

## Releasing / version bumps

Expand Down
44 changes: 21 additions & 23 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"types": "dist/index.d.ts",
"repository": "https://github.com/glideapps/quicktype",
"engines": {
"node": ">=20.0.0"
"node": ">=20.19.0"
},
"scripts": {
"pub": "script/publish-npm.sh && script/publish-vscode.sh",
Expand Down Expand Up @@ -48,7 +48,7 @@
"quicktype-graphql-input": "24.0.0",
"quicktype-typescript-input": "24.0.0",
"readable-stream": "^4.5.2",
"stream-json": "1.8.0",
"stream-json": "3.5.0",
"string-to-stream": "^3.0.1",
"wordwrap": "^1.0.0"
},
Expand All @@ -61,7 +61,6 @@
"@types/node": "~20.19.0",
"@types/semver": "^7.5.0",
"@types/shelljs": "^0.10.0",
"@types/stream-json": "^1.7.3",
"@types/urijs": "^1.19.26",
"@types/wordwrap": "^1.0.3",
"ajv": "^8.20.0",
Expand Down
5 changes: 1 addition & 4 deletions packages/quicktype-core/src/ConvenienceRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -995,10 +995,7 @@ export abstract class ConvenienceRenderer extends Renderer {
f: (name: Name, jsonName: string, position: ForEachPosition) => void,
): void {
const caseNames = defined(this._caseNamesStoreView).get(e);
const sortedCaseNames = mapSortBy(caseNames, (n) =>
defined(this.names.get(n)),
);
this.forEachWithBlankLines(sortedCaseNames, blankLocations, f);
this.forEachWithBlankLines(caseNames, blankLocations, f);
}

protected forEachTransformation(
Expand Down
10 changes: 8 additions & 2 deletions packages/quicktype-core/src/GraphRewriting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,14 @@ export class TypeReconstituter<TBuilder extends BaseGraphRewriteBuilder> {
}

public getUniqueArrayType(): void {
this.registerAndAddAttributes(
this.builderForNewType().getUniqueArrayType(this._forwardingRef),
// The attributes must be passed at creation, not added
// afterwards with `addAttributes`, which would assert on
// identity attributes such as minItems/maxItems.
this.register(
this.builderForNewType().getUniqueArrayType(
this._typeAttributes,
this._forwardingRef,
),
);
}

Expand Down
7 changes: 5 additions & 2 deletions packages/quicktype-core/src/Type/TypeBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -479,11 +479,14 @@ export class TypeBuilder {
this.registerType(type);
}

public getUniqueArrayType(forwardingRef?: TypeRef): TypeRef {
public getUniqueArrayType(
attributes?: TypeAttributes,
forwardingRef?: TypeRef,
): TypeRef {
return this.addType(
forwardingRef,
(tr) => new ArrayType(tr, this.typeGraph, undefined),
undefined,
attributes,
);
}

Expand Down
28 changes: 27 additions & 1 deletion packages/quicktype-core/src/attributes/Constraints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export class MinMaxConstraintTypeAttributeKind extends TypeAttributeKind<MinMaxC
t: Type,
attr: MinMaxConstraint,
): void {
if (this._typeKinds.has(t.kind)) return;
if (!this._typeKinds.has(t.kind)) return;

const [min, max] = attr;
if (min !== undefined) {
Expand Down Expand Up @@ -130,6 +130,14 @@ export const minMaxLengthTypeAttributeKind: TypeAttributeKind<MinMaxConstraint>
"maxLength",
);

export const minMaxItemsTypeAttributeKind: TypeAttributeKind<MinMaxConstraint> =
new MinMaxConstraintTypeAttributeKind(
"minMaxItems",
new Set<TypeKind>(["array"]),
"minItems",
"maxItems",
);

function producer(
schema: JSONSchema,
minProperty: string,
Expand Down Expand Up @@ -179,6 +187,20 @@ export function minMaxLengthAttributeProducer(
};
}

export function minMaxItemsAttributeProducer(
schema: JSONSchema,
_ref: Ref,
types: Set<JSONSchemaType>,
): JSONSchemaAttributes | undefined {
if (!types.has("array")) return undefined;

const maybeMinMaxItems = producer(schema, "minItems", "maxItems");
if (maybeMinMaxItems === undefined) return undefined;
return {
forArray: minMaxItemsTypeAttributeKind.makeAttributes(maybeMinMaxItems),
};
}

export function minMaxValueForType(t: Type): MinMaxConstraint | undefined {
return minMaxTypeAttributeKind.tryGetInAttributes(t.getAttributes());
}
Expand All @@ -187,6 +209,10 @@ export function minMaxLengthForType(t: Type): MinMaxConstraint | undefined {
return minMaxLengthTypeAttributeKind.tryGetInAttributes(t.getAttributes());
}

export function minMaxItemsForType(t: Type): MinMaxConstraint | undefined {
return minMaxItemsTypeAttributeKind.tryGetInAttributes(t.getAttributes());
}

export class PatternTypeAttributeKind extends TypeAttributeKind<string> {
public constructor() {
super("pattern");
Expand Down
26 changes: 21 additions & 5 deletions packages/quicktype-core/src/input/JSONSchemaInput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import URI from "urijs";
import { accessorNamesAttributeProducer } from "../attributes/AccessorNames.js";
import {
minMaxAttributeProducer,
minMaxItemsAttributeProducer,
minMaxLengthAttributeProducer,
patternAttributeProducer,
} from "../attributes/Constraints.js";
Expand Down Expand Up @@ -306,7 +307,7 @@ export class Ref {
public get definitionName(): string | undefined {
const pe = arrayGetFromEnd(this.path, 2);
if (pe === undefined) return undefined;
if (keyOrIndex(pe) === "definitions")
if (keyOrIndex(pe) === "definitions" || keyOrIndex(pe) === "$defs")
return keyOrIndex(defined(arrayLast(this.path)));
return undefined;
}
Expand Down Expand Up @@ -649,6 +650,7 @@ const schemaTypes = Object.getOwnPropertyNames(
) as JSONSchemaType[];

export interface JSONSchemaAttributes {
forArray?: TypeAttributes;
forCases?: TypeAttributes[];
forNumber?: TypeAttributes;
forObject?: TypeAttributes;
Expand Down Expand Up @@ -783,7 +785,7 @@ class Resolver {
return [schema, result[1]];
}

return schemaFetchError(base, virtualRef.address);
return schemaFetchError(base, virtualRef.toString());
}

public async resolveTopLevelRef(ref: Ref): Promise<[JSONSchema, Location]> {
Expand Down Expand Up @@ -1031,7 +1033,9 @@ async function addTypesInSchema(
return typeBuilder.getPrimitiveType(kind, attributes);
}

async function makeArrayType(): Promise<TypeRef> {
async function makeArrayType(
arrayAttributes: TypeAttributes,
): Promise<TypeRef> {
const singularAttributes = singularizeTypeNames(typeAttributes);
const items = schema.items;
// JSON Schema 2020-12 renamed the array (tuple) form of `items` to
Expand Down Expand Up @@ -1097,7 +1101,7 @@ async function addTypesInSchema(
}

typeBuilder.addAttributes(itemType, singularAttributes);
return typeBuilder.getArrayType(emptyTypeAttributes, itemType);
return typeBuilder.getArrayType(arrayAttributes, itemType);
}

async function makeObjectType(): Promise<TypeRef> {
Expand Down Expand Up @@ -1139,6 +1143,14 @@ async function addTypesInSchema(
additionalProperties = schema.patternProperties[".*"];
}

// Handle unevaluatedProperties if additionalProperties is not defined
if (
additionalProperties === undefined &&
schema.unevaluatedProperties !== undefined
) {
additionalProperties = schema.unevaluatedProperties;
}

const objectAttributes = combineTypeAttributes(
"union",
inferredAttributes,
Expand Down Expand Up @@ -1314,7 +1326,10 @@ async function addTypesInSchema(
}

if (includeArray) {
unionTypes.push(await makeArrayType());
const arrayAttributes = combineProducedAttributes(
({ forArray }) => forArray,
);
unionTypes.push(await makeArrayType(arrayAttributes));
}

if (includeObject) {
Expand Down Expand Up @@ -1549,6 +1564,7 @@ export class JSONSchemaInput implements Input<JSONSchemaSourceData> {
uriSchemaAttributesProducer,
minMaxAttributeProducer,
minMaxLengthAttributeProducer,
minMaxItemsAttributeProducer,
patternAttributeProducer,
].concat(additionalAttributeProducers);
}
Expand Down
5 changes: 5 additions & 0 deletions packages/quicktype-core/src/input/io/NodeIO.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,11 @@ export async function readableFromFileOrURL(
const response = await globalThis.fetch(fileOrURL, {
headers: parseHeaders(httpHeaders),
});
if (!response.ok) {
throw new Error(
`HTTP ${response.status} ${response.statusText}`,
);
}

return readableFromResponseBody(defined(response.body));
}
Expand Down
Loading
Loading