Skip to content

Commit

Permalink
fix: all tests pass - including vega-lite!
Browse files Browse the repository at this point in the history
  • Loading branch information
sramam committed Feb 20, 2021
1 parent ab6eafb commit fa9b8b5
Show file tree
Hide file tree
Showing 29 changed files with 374 additions and 384 deletions.
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
"ajv": "^7.1.1",
"ajv-formats": "^1.5.1",
"chai": "^4.3.0",
"cross-env": "^7.0.3",
"eslint": "^7.20.0",
"eslint-config-prettier": "^7.2.0",
"eslint-plugin-prettier": "^3.3.1",
Expand All @@ -82,11 +83,12 @@
"lint": "eslint {src,test,factory}/**/*.ts",
"format": "yarn lint --fix",
"test": "jest test/ --verbose",
"test:fast": "FAST_TEST=1 jest test/ --verbose",
"test:fast": "cross-env FAST_TEST=1 jest test/ --verbose",
"test:coverage": "yarn jest test/ --collectCoverage=true",
"test:update": "UPDATE_SCHEMA=true yarn test:fast",
"test:update": "cross-env UPDATE_SCHEMA=true yarn test:fast",
"debug": "node -r ts-node/register --inspect-brk ts-json-schema-generator.ts",
"dbg": "node -r ts-node/register --inspect-brk ts-json-schema-generator.ts -p test/valid-data/duplicates-composition/main.ts -t MyObject",
"dbg": "node -r ts-node/register --inspect-brk ts-json-schema-generator.ts -p test/valid-data/type-aliases-recursive-anonymous/main.ts -t MyAlias",
"dbg-vega": "node -r ts-node/register --inspect-brk ts-json-schema-generator.ts -p ../../../tmp/vega-lite/src/index.ts -t TopLevelSpec --no-type-check --no-ref-encode > ../../../tmp/vega-lite/build/vega-lite-schema2.json",
"run": "ts-node ts-json-schema-generator.ts"
},
"release": {
Expand Down
49 changes: 26 additions & 23 deletions src/SchemaGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ import { removeUnreachable } from "./Utils/removeUnreachable";
import { Config } from "./Config";
import { hasJsDocTag } from "./Utils/hasJsDocTag";
import { JSONSchema7, JSONSchema7Definition } from "json-schema";
import { derefType } from "./Utils/derefType";
import { AliasType } from "./Type/AliasType";
import { ObjectType } from "./Type/ObjectType";

export class SchemaGenerator {
public constructor(
Expand Down Expand Up @@ -40,22 +43,6 @@ export class SchemaGenerator {
rootTypes.forEach((rootType) => this.appendRootChildDefinitions(rootType, definitions, idNameMap));
const reachableDefinitions = removeUnreachable(rootTypeDefinition, definitions);

if (true) {
// TODO: remove this.
console.log(
JSON.stringify(
{
rootTypeDefinition,
definitions,
reachableDefinitions,
},
null,
2
)
);
console.log(idNameMap);
}

// create schema - all $ref's use getId().
const schema: JSONSchema7Definition = {
...(this.config?.schemaId ? { $id: this.config.schemaId } : {}),
Expand Down Expand Up @@ -121,19 +108,19 @@ export class SchemaGenerator {

const duplicates: StringMap<Set<DefinitionType>> = {};
for (const child of children) {
const name = child.getName(); // .replace(/^def-interface/, "interface");
const name = child.getName();
duplicates[name] = duplicates[name] ?? new Set<DefinitionType>();
duplicates[name].add(child);
}

children.reduce((definitions, child) => {
const id = child.getId(); // .replace(/^def-interface/, "interface");
const id = child.getId().replace(/^def-/, "");
if (!(id in definitions)) {
const name = unambiguousName(child, child === rootType, [...duplicates[child.getName()]]);
// Record the schema against the ID, allowing steps like removeUnreachable to work
definitions[id] = this.typeFormatter.getDefinition(child.getType());
// Create a record of id->name mapping. This is used in the final step
// to resolve id -> name before delivering the schema to caller.
const name = unambiguousName(child, child === rootType, [...duplicates[child.getName()]]);
idNameMap.set(id, name);
}
return definitions;
Expand Down Expand Up @@ -222,17 +209,33 @@ function getCommonPrefixes(paths: string[]) {
);
}

function unambiguousName(child: DefinitionType, isRoot: boolean, peers: DefinitionType[]) {
function unambiguousName(child: DefinitionType, isRoot: boolean, peers: DefinitionType[]): string {
if (peers.length === 1 || isRoot) {
return child.getName();
} else {
} else if (child.getType().getSrcFileName()) {
let index = -1;
const srcPaths = peers.map((peer: DefinitionType, count) => {

// filter unique peers to be those that have srcFileNames.
// Intermediate Types - AnnotationTypes, UnionTypes, do not have sourceFileNames
const uniques = peers.filter((peer) => peer.getType().getSrcFileName());
if (uniques.length === 1) {
return uniques[0].getName();
}
const srcPaths = uniques.map((peer: DefinitionType, count) => {
index = child === peer ? count : index;
return peer.getType().getSrcFileName();
return peer.getType().getSrcFileName()!;
});
const prefixes = getCommonPrefixes(srcPaths);
return `${prefixes[index]}-${child.getName()}`;
} else {
// intermediate type.
const name = child.getName();
// TODO: Perhaps we should maintain a name-id map, and throw a duplicate error on collision.
if (name === undefined) {
// this might be unreachable code.
throw new Error(`Unable to disambiguate types`);
}
return name;
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/Type/BaseType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export abstract class BaseType {
* Provide a base class implementation. Will only be exported for entities
* exposed in a schema - Alias|Enum|Class|Interface.
*/
public getSrcFileName(): string {
throw new Error(`Missing sourceFileName '${this.getId()}'`);
public getSrcFileName(): string | null {
return null;
}
}
2 changes: 1 addition & 1 deletion src/Type/DefinitionType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export class DefinitionType extends BaseType {
return this.type;
}

public getSrcFileName(): string {
public getSrcFileName(): string | null {
return this.type.getSrcFileName();
}
}
2 changes: 1 addition & 1 deletion src/TypeFormatter/DefinitionTypeFormatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export class DefinitionTypeFormatter implements SubTypeFormatter {
return type instanceof DefinitionType;
}
public getDefinition(type: DefinitionType): Definition {
const ref = type.getId();
const ref = type.getId().replace(/^def-/, "");
return { $ref: `#/definitions/${this.encodeRefs ? encodeURIComponent(ref) : ref}` };
}
public getChildren(type: DefinitionType): BaseType[] {
Expand Down
2 changes: 1 addition & 1 deletion src/TypeFormatter/ReferenceTypeFormatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export class ReferenceTypeFormatter implements SubTypeFormatter {
return type instanceof ReferenceType;
}
public getDefinition(type: ReferenceType): Definition {
const ref = type.getId();
const ref = type.getId().replace(/^def-/, "");
return { $ref: `#/definitions/${this.encodeRefs ? encodeURIComponent(ref) : ref}` };
}
public getChildren(type: ReferenceType): BaseType[] {
Expand Down
1 change: 1 addition & 0 deletions test/valid-data/annotation-custom/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@
"customUnquotedProperty": "not-a-valid-json",
"type": "object"
}
}
}
96 changes: 48 additions & 48 deletions test/valid-data/class-generics/schema.json
Original file line number Diff line number Diff line change
@@ -1,54 +1,54 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$ref": "#/definitions/MyObject",
"definitions": {
"MyObject": {
"type": "object",
"required": [
"a",
"b",
"c",
"d"
],
"properties": {
"a": {
"type": "number"
},
"b": {
"type": "string"
},
"c": {
"$ref": "#/definitions/Base%3Cstring%3E"
},
"d": {
"$ref": "#/definitions/Base%3Cboolean%3E"
}
},
"additionalProperties": false
"$ref": "#/definitions/MyObject",
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"Base<boolean>": {
"additionalProperties": false,
"properties": {
"a": {
"type": "boolean"
}
},
"required": [
"a"
],
"type": "object"
},
"Base<string>": {
"additionalProperties": false,
"properties": {
"a": {
"type": "string"
}
},
"required": [
"a"
],
"type": "object"
},
"MyObject": {
"additionalProperties": false,
"properties": {
"a": {
"type": "number"
},
"b": {
"type": "string"
},
"Base<string>": {
"type": "object",
"required": [
"a"
],
"properties": {
"a": {
"type": "string"
}
},
"additionalProperties": false
"c": {
"$ref": "#/definitions/Base%3Cstring%3E"
},
"Base<boolean>": {
"type": "object",
"required": [
"a"
],
"properties": {
"a": {
"type": "boolean"
}
},
"additionalProperties": false
"d": {
"$ref": "#/definitions/Base%3Cboolean%3E"
}
},
"required": [
"a",
"b",
"c",
"d"
],
"type": "object"
}
}
}
82 changes: 41 additions & 41 deletions test/valid-data/duplicates-composition/schema.json
Original file line number Diff line number Diff line change
@@ -1,46 +1,46 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$ref": "#/definitions/MyObject",
"definitions": {
"MyObject": {
"type": "object",
"required": [
"a",
"b"
],
"properties": {
"a": {
"$ref": "#/definitions/componentA-MyObject"
},
"b": {
"$ref": "#/definitions/componentB-MyObject"
}
},
"additionalProperties": false
"$ref": "#/definitions/MyObject",
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"MyObject": {
"additionalProperties": false,
"properties": {
"a": {
"$ref": "#/definitions/componentA-MyObject"
},
"componentA-MyObject": {
"type": "object",
"required": [
"a"
],
"properties": {
"a": {
"type": "string"
}
},
"additionalProperties": false
},
"componentB-MyObject": {
"type": "object",
"required": [
"b"
],
"properties": {
"b": {
"type": "string"
}
},
"additionalProperties": false
"b": {
"$ref": "#/definitions/componentB-MyObject"
}
},
"required": [
"a",
"b"
],
"type": "object"
},
"componentA-MyObject": {
"additionalProperties": false,
"properties": {
"a": {
"type": "string"
}
},
"required": [
"a"
],
"type": "object"
},
"componentB-MyObject": {
"additionalProperties": false,
"properties": {
"b": {
"type": "string"
}
},
"required": [
"b"
],
"type": "object"
}
}
}
Loading

0 comments on commit fa9b8b5

Please sign in to comment.