-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
fix(typescript): preserve top-level array types from JSON Schema #3031
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
9def64c
fix(typescript): preserve top-level array types from JSON Schema (#2481)
schani e6b74f9
test: add missing fixture cases for top-level-array.schema and top-le…
e3f66fe
Merge origin/master into agent/fix-issue-2481
schani d5659bc
test: skip top-level-array schemas for kotlinx and php
schani 3ee5061
Merge commit '3061a7bd52c02eebde32dc0c6fb46069f0ebc0a4' into luna-tri…
schani 6a9ae35
test(kotlin): skip unsupported top-level array schemas
schani 180c352
Merge remote-tracking branch 'origin/master' into agent/fix-issue-2481
schani d1ae26a
test(zod): skip unsupported top-level array schemas
schani c4b36b3
test: skip unsupported top-level array validation
schani 587192b
test: focus top-level array fixtures on generation
schani 000096c
test(elixir): skip unsupported top-level array schemas
schani 54bf41b
fix(schema): use standard comment for array provenance
schani 14bb929
Merge origin/master into agent/fix-issue-2481
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| import { TypeAttributeKind } from "./TypeAttributes.js"; | ||
|
|
||
| export type SchemaArrayProvenance = "explicit" | "inferred"; | ||
|
|
||
| class SchemaArrayTypeAttributeKind extends TypeAttributeKind<SchemaArrayProvenance> { | ||
| public constructor() { | ||
| super("schemaArrayProvenance"); | ||
| } | ||
|
|
||
| public combine(attrs: SchemaArrayProvenance[]): SchemaArrayProvenance { | ||
| return attrs.includes("explicit") ? "explicit" : "inferred"; | ||
| } | ||
|
|
||
| public makeInferred(attr: SchemaArrayProvenance): SchemaArrayProvenance { | ||
| return attr; | ||
| } | ||
| } | ||
|
|
||
| export const schemaArrayTypeAttributeKind = new SchemaArrayTypeAttributeKind(); | ||
|
|
||
| // Preserve sample-inference semantics when a top-level array is round-tripped | ||
| // through quicktype's JSON Schema output. | ||
| export const inferredTopLevelSchemaComment = "qt-inferred-top-level"; | ||
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
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
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| [ | ||
| { "label": "positive", "score": 0.95 }, | ||
| { "label": "negative", "score": 0.05 } | ||
| ] |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| { | ||
| "$schema": "http://json-schema.org/draft-06/schema#", | ||
| "title": "TextClassificationOutput", | ||
| "type": "array", | ||
| "items": { | ||
| "type": "object", | ||
| "title": "TextClassificationOutputElement", | ||
| "properties": { | ||
| "label": { "type": "string" }, | ||
| "score": { "type": "number" } | ||
| }, | ||
| "required": ["label", "score"] | ||
| } | ||
| } |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| ["one", "two", "three"] |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| { | ||
| "$schema": "http://json-schema.org/draft-06/schema#", | ||
| "title": "SomeInput", | ||
| "type": "array", | ||
| "items": { "type": "string" } | ||
| } |
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| import fs from "node:fs"; | ||
|
|
||
| import { describe, expect, test } from "vitest"; | ||
|
|
||
| import { | ||
| InputData, | ||
| JSONSchemaInput, | ||
| jsonInputForTargetLanguage, | ||
| quicktype, | ||
| } from "quicktype-core"; | ||
|
|
||
| async function typesForSchema(filename: string, name: string): Promise<string> { | ||
| const schemaInput = new JSONSchemaInput(undefined); | ||
| await schemaInput.addSource({ | ||
| name, | ||
| schema: fs.readFileSync(`test/inputs/schema/${filename}`, "utf8"), | ||
| }); | ||
| const inputData = new InputData(); | ||
| inputData.addInput(schemaInput); | ||
| const result = await quicktype({ | ||
| inputData, | ||
| lang: "typescript", | ||
| rendererOptions: { "just-types": true }, | ||
| }); | ||
| return result.lines.join("\n"); | ||
| } | ||
|
|
||
| async function typesForJSON(name: string, sample: string): Promise<string> { | ||
| const jsonInput = jsonInputForTargetLanguage("typescript"); | ||
| await jsonInput.addSource({ name, samples: [sample] }); | ||
| const inputData = new InputData(); | ||
| inputData.addInput(jsonInput); | ||
| const result = await quicktype({ | ||
| inputData, | ||
| lang: "typescript", | ||
| rendererOptions: { "just-types": true }, | ||
| }); | ||
| return result.lines.join("\n"); | ||
| } | ||
|
|
||
| async function typesForJSONViaSchema( | ||
| name: string, | ||
| sample: string, | ||
| ): Promise<string> { | ||
| const jsonInput = jsonInputForTargetLanguage("schema"); | ||
| await jsonInput.addSource({ name, samples: [sample] }); | ||
| const inputData = new InputData(); | ||
| inputData.addInput(jsonInput); | ||
| const schema = await quicktype({ inputData, lang: "schema" }); | ||
|
|
||
| const schemaInput = new JSONSchemaInput(undefined); | ||
| await schemaInput.addSource({ name, schema: schema.lines.join("\n") }); | ||
| const schemaInputData = new InputData(); | ||
| schemaInputData.addInput(schemaInput); | ||
| const result = await quicktype({ | ||
| inputData: schemaInputData, | ||
| lang: "typescript", | ||
| rendererOptions: { "just-types": true }, | ||
| }); | ||
| return result.lines.join("\n"); | ||
| } | ||
|
|
||
| describe("TypeScript top-level arrays", () => { | ||
| test("schema array emits an alias and preserves the item title", async () => { | ||
| const output = await typesForSchema( | ||
| "top-level-array.schema", | ||
| "TextClassificationOutput", | ||
| ); | ||
|
|
||
| expect(output).toContain( | ||
| "export type TextClassificationOutput = TextClassificationOutputElement[];", | ||
| ); | ||
| expect(output).toContain( | ||
| "export interface TextClassificationOutputElement", | ||
| ); | ||
| }); | ||
|
|
||
| test("schema array of primitives emits an alias", async () => { | ||
| const output = await typesForSchema( | ||
| "top-level-primitive-array.schema", | ||
| "SomeInput", | ||
| ); | ||
|
|
||
| expect(output).toContain("export type SomeInput = string[];"); | ||
| }); | ||
|
|
||
| test("JSON sample arrays still collapse to the element type", async () => { | ||
| const sample = '[{"label":"a","score":1},{"label":"b","score":2}]'; | ||
| const output = await typesForJSON("Sample", sample); | ||
|
|
||
| expect(output).toContain("export interface Sample"); | ||
| expect(output).not.toContain("export type Sample ="); | ||
| expect(await typesForJSONViaSchema("Sample", sample)).toBe(output); | ||
| }); | ||
|
|
||
| test("JSON primitive arrays still round-trip without an alias", async () => { | ||
| const sample = '["one","two"]'; | ||
| const output = await typesForJSON("Sample", sample); | ||
|
|
||
| expect(output).toBe(""); | ||
| expect(await typesForJSONViaSchema("Sample", sample)).toBe(output); | ||
| }); | ||
| }); |
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is stupid. Remove this, and fix the fallout properly!